├── .DS_Store ├── .circleci ├── config.yml └── github_key ├── .eslintrc ├── .gitattributes ├── .gitignore ├── .prettierrc ├── INTERACTIONS.md ├── LICENSE ├── README.md ├── assets ├── .DS_Store ├── animation │ └── eye_outline_animation_long.svg ├── arrows │ ├── .DS_Store │ ├── Price_Arrow_Down.svg │ ├── Price_Arrow_Up.svg │ ├── Scroll_Arrow_Down.png │ ├── Scroll_Arrow_Down.svg │ ├── Scroll_Arrow_Up.png │ └── Scroll_Arrow_Up.svg ├── glyphs v1 │ ├── .DS_Store │ ├── 24px │ │ ├── .DS_Store │ │ ├── Glyph_Chart 24px.svg │ │ ├── Glyph_Chart_Compressed.svg │ │ ├── Glyph_Drag 24px.svg │ │ ├── Glyph_Left 24px.svg │ │ ├── Glyph_News 24px.svg │ │ ├── Glyph_News_Compressed.svg │ │ ├── Glyph_Opacity 24px.svg │ │ ├── Glyph_Right 24px.svg │ │ ├── Glyph_Search 24px.svg │ │ ├── Glyph_Top 24px.svg │ │ ├── Glyph_Watchlist 24px.svg │ │ └── Glyph_Watchlist_Compressed.svg │ └── 30px │ │ ├── Glyph_Chart 30px.svg │ │ ├── Glyph_Closesvg.svg │ │ ├── Glyph_Drag 30px.svg │ │ ├── Glyph_Left 30px.svg │ │ ├── Glyph_Minimize.svg │ │ ├── Glyph_News 30px.svg │ │ ├── Glyph_Opacity 30px.svg │ │ ├── Glyph_Right 30px.svg │ │ ├── Glyph_Search 30px.svg │ │ ├── Glyph_Top 30px.svg │ │ └── Glyph_Watchlist 30px.svg ├── icons v1 │ ├── .DS_Store │ ├── Icon_Chart.svg │ ├── Icon_Drag.svg │ ├── Icon_Left.svg │ ├── Icon_Link.svg │ ├── Icon_News.svg │ ├── Icon_Opacity.svg │ ├── Icon_Pin.svg │ ├── Icon_Right.svg │ ├── Icon_Search.svg │ ├── Icon_Top.svg │ └── Icon_Watchlist.svg ├── logos │ └── D3FC Logo.svg └── specs │ ├── .DS_Store │ ├── Chart Ref.svg │ ├── Chart Specs.svg │ ├── Launcher Reference.svg │ ├── Launcher Specs.svg │ ├── News Ref.svg │ ├── News Specs.svg │ ├── Search Results Specs.svg │ ├── Specs.sketch │ ├── Tooltip Specs.svg │ ├── Watched Stock Specs.svg │ ├── Watchlist Behaviours.svg │ ├── Watchlist Specs Export.svg │ ├── Watchlist Specs.svg │ ├── Watchlist empty state specs.svg │ └── Watchlist reference.svg ├── communication-dependencies.PNG ├── developer-proxy ├── package-lock.json ├── package.json ├── readMe.md └── src │ ├── config.js │ ├── index.js │ ├── proxyOverride.js │ └── static │ ├── apps.json │ ├── chart.app.json │ ├── news.app.json │ └── watchlist.app.json ├── kill.bat ├── lerna.json ├── package-dependencies.PNG ├── package-lock.json ├── package.json ├── packages ├── stockflux-chart │ ├── README.md │ ├── package-lock.json │ ├── package.json │ ├── public │ │ ├── app.dev.json │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── launcher.png │ │ ├── manifest.json │ │ └── splashscreen.png │ └── src │ │ ├── App.js │ │ ├── assets │ │ ├── d3fc.svg │ │ └── png │ │ │ └── close_indicator.png │ │ ├── components │ │ ├── Chart.js │ │ └── chart.css │ │ ├── index.js │ │ ├── reducers │ │ └── open-apps │ │ │ ├── Action.js │ │ │ └── OpenApps.js │ │ └── styles │ │ └── app.css ├── stockflux-components │ ├── .babelrc │ ├── README.md │ ├── package-lock.json │ ├── package.json │ ├── src │ │ ├── components │ │ │ ├── Titlebar │ │ │ │ ├── Titlebar.css │ │ │ │ └── Titlebar.js │ │ │ ├── buttons │ │ │ │ ├── borderless-button │ │ │ │ │ ├── BorderlessButton.css │ │ │ │ │ └── BorderlessButton.js │ │ │ │ ├── borderless-buttons │ │ │ │ │ ├── Close.js │ │ │ │ │ └── app-shortcuts │ │ │ │ │ │ ├── Chart.js │ │ │ │ │ │ ├── External.js │ │ │ │ │ │ ├── News.js │ │ │ │ │ │ └── Watchlist.js │ │ │ │ ├── dialog-button │ │ │ │ │ ├── DialogButton.css │ │ │ │ │ └── DialogButton.js │ │ │ │ └── round-button │ │ │ │ │ ├── RoundButton.css │ │ │ │ │ └── RoundButton.js │ │ │ ├── glyphs │ │ │ │ ├── arrows │ │ │ │ │ ├── priceArrowDown.svg │ │ │ │ │ └── priceArrowUp.svg │ │ │ │ ├── launcher │ │ │ │ │ ├── chart.svg │ │ │ │ │ ├── left.svg │ │ │ │ │ ├── news.svg │ │ │ │ │ ├── right.svg │ │ │ │ │ ├── search.svg │ │ │ │ │ ├── top.svg │ │ │ │ │ └── watchlist.svg │ │ │ │ ├── normal │ │ │ │ │ ├── chart.svg │ │ │ │ │ ├── news.svg │ │ │ │ │ └── watchlist.svg │ │ │ │ └── small │ │ │ │ │ ├── chart.svg │ │ │ │ │ ├── hide.svg │ │ │ │ │ ├── news.svg │ │ │ │ │ ├── remove.svg │ │ │ │ │ ├── reveal.svg │ │ │ │ │ └── watchlist.svg │ │ │ ├── icons │ │ │ │ ├── chart.svg │ │ │ │ ├── close.svg │ │ │ │ ├── link.svg │ │ │ │ ├── minimize.svg │ │ │ │ ├── news.svg │ │ │ │ └── watchlist.svg │ │ │ ├── popups │ │ │ │ ├── ConfirmationWindow.js │ │ │ │ ├── PopupWindow.js │ │ │ │ └── getUndockedPosition.js │ │ │ ├── preview-window │ │ │ │ └── PreviewWindow.js │ │ │ ├── scroll-wrapper-y │ │ │ │ ├── ScrollWrapperY.css │ │ │ │ └── ScrollWrapperY.js │ │ │ └── spinner │ │ │ │ ├── Spinner.css │ │ │ │ └── Spinner.js │ │ ├── images │ │ │ ├── arrow_down.png │ │ │ ├── arrow_up.png │ │ │ ├── close.png │ │ │ ├── close_active.png │ │ │ ├── close_indicator.png │ │ │ ├── compact.png │ │ │ ├── compact_active.png │ │ │ ├── full_view.png │ │ │ ├── full_view_active.png │ │ │ ├── index.js │ │ │ ├── maximize.png │ │ │ ├── maximize_active.png │ │ │ ├── minimize.png │ │ │ ├── minimize_active.png │ │ │ ├── no_starred.png │ │ │ ├── normal_size.png │ │ │ ├── normal_size_active.png │ │ │ ├── scottlogic_logo.png │ │ │ ├── scroll_arrow_down.png │ │ │ ├── scroll_arrow_up.png │ │ │ ├── search_tab.png │ │ │ ├── star_hover.png │ │ │ ├── star_off.png │ │ │ ├── star_off_hover.png │ │ │ ├── star_on.png │ │ │ ├── star_tab.png │ │ │ ├── undock.png │ │ │ └── undock_active.png │ │ ├── index.css │ │ ├── index.js │ │ └── styles │ │ │ ├── button-icon.css │ │ │ ├── font.css │ │ │ ├── icon.css │ │ │ └── scrollbar.css │ └── webpack.config.js ├── stockflux-container │ ├── README.md │ ├── package-lock.json │ ├── package.json │ ├── public │ │ ├── app.dev.json │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── launcher.png │ │ ├── manifest.json │ │ └── splashscreen.png │ └── src │ │ ├── App.js │ │ ├── index.js │ │ └── serviceWorker.js ├── stockflux-core │ ├── README.md │ ├── package-lock.json │ ├── package.json │ ├── src │ │ ├── custom-hooks │ │ │ └── LocalStorageHook.js │ │ ├── index.js │ │ ├── intents │ │ │ ├── addWatchlist.js │ │ │ ├── index.js │ │ │ ├── viewChart.js │ │ │ ├── viewNews.js │ │ │ └── viewWatchlist.js │ │ ├── openfin-api-utils │ │ │ └── openfinApiHelpers.js │ │ ├── services │ │ │ ├── ChildWindowLauncher.js │ │ │ ├── StockFluxService.js │ │ │ └── app-launchers │ │ │ │ ├── Chart.js │ │ │ │ ├── News.js │ │ │ │ ├── Watchlist.js │ │ │ │ └── index.js │ │ └── utils │ │ │ └── formatters.js │ └── webpack.config.js ├── stockflux-launcher │ ├── README.md │ ├── package-lock.json │ ├── package.json │ ├── public │ │ ├── app.dev.json │ │ ├── child-window.html │ │ ├── childWindow.css │ │ ├── dockSelector.css │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── launcher.png │ │ ├── manifest.json │ │ ├── popupWindow.css │ │ └── splashscreen.png │ └── src │ │ ├── App.css │ │ ├── App.js │ │ ├── app-shortcuts │ │ ├── AppShortcuts.css │ │ └── AppShortcuts.js │ │ ├── dock-selector │ │ ├── DockSelector.css │ │ ├── DockSelector.js │ │ ├── GetSelectionWindowProps.js │ │ └── Positioner.js │ │ ├── free-text-search │ │ ├── FreeTextSearch.css │ │ ├── FreeTextSearch.js │ │ ├── SearchButton.js │ │ └── SearchInputField.js │ │ ├── helpers │ │ └── getUndockedPosition.js │ │ ├── index.css │ │ ├── index.js │ │ ├── reducers │ │ ├── child-window │ │ │ ├── Action.js │ │ │ ├── ChildWindow.js │ │ │ └── State.js │ │ ├── free-text-search │ │ │ ├── Action.js │ │ │ └── FreeTextSearch.js │ │ └── search-result │ │ │ ├── Action.js │ │ │ └── SearchResult.js │ │ ├── search-results │ │ ├── ChildWindow.js │ │ ├── Launcher.js │ │ ├── SearchResult.js │ │ ├── SearchResults.js │ │ ├── helpers │ │ │ ├── GetResultsWindowProps.js │ │ │ ├── Launcher.js │ │ │ ├── Populater.js │ │ │ ├── Positioner.js │ │ │ └── useChildWindow.js │ │ └── messages.js │ │ └── toolbar │ │ ├── CloseButton.js │ │ ├── ToolBar.css │ │ └── ToolBar.js ├── stockflux-news │ ├── README.md │ ├── package-lock.json │ ├── package.json │ ├── public │ │ ├── app.dev.json │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── launcher.png │ │ ├── manifest.json │ │ └── splashscreen.png │ └── src │ │ ├── App.css │ │ ├── App.js │ │ ├── components │ │ └── news-item │ │ │ ├── NewsItem.css │ │ │ ├── NewsItem.js │ │ │ └── index.js │ │ ├── index.css │ │ ├── index.js │ │ └── serviceWorker.js └── stockflux-watchlist │ ├── README.md │ ├── package-lock.json │ ├── package.json │ ├── public │ ├── ArrowUp.png │ ├── CardIcon.png │ ├── animation-assets │ │ └── eye_outline_animation_long.svg │ ├── app.dev.json │ ├── child-window.html │ ├── childWindow.css │ ├── delete-symbol.html │ ├── favicon.ico │ ├── index.html │ ├── launcher.png │ ├── manifest.json │ ├── notification.css │ ├── notification.html │ ├── popupWindow.css │ ├── preview-chart.html │ ├── splashscreen.png │ └── sprite.svg │ └── src │ ├── App.css │ ├── App.js │ ├── components │ ├── PreviewOptions.js │ ├── minichart │ │ ├── Minichart.css │ │ ├── Minichart.js │ │ └── constants.js │ └── watchlist-card │ │ ├── WatchlistCard.Dragging.js │ │ ├── WatchlistCard.css │ │ └── WatchlistCard.js │ ├── icons │ ├── chart.svg │ ├── news.svg │ └── watchlist.svg │ ├── index.js │ ├── reducers │ └── open-apps │ │ ├── Action.js │ │ └── OpenApps.js │ └── services │ └── currentWindowService.js └── stockflux.png /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/.DS_Store -------------------------------------------------------------------------------- /.circleci/github_key: -------------------------------------------------------------------------------- 1 | github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ== -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es6": true, 5 | "jest": true 6 | }, 7 | "extends": ["eslint:recommended", "prettier", "react-app"], 8 | "parser": "babel-eslint", 9 | "parserOptions": { 10 | "ecmaVersion": 2018, 11 | "sourceType": "module", 12 | "ecmaFeatures": { 13 | "jsx": true 14 | } 15 | }, 16 | "plugins": ["prettier"], 17 | "rules": { 18 | "no-case-declarations": "off", 19 | "no-console": [ 20 | "error", 21 | { 22 | "allow": ["error"] 23 | } 24 | ], 25 | "no-multi-str": "off", 26 | "no-trailing-spaces": "error", 27 | "no-unused-vars": [ 28 | "error", 29 | { 30 | "argsIgnorePattern": "^_" 31 | } 32 | ], 33 | "prettier/prettier": "error", 34 | "quotes": ["error", "single"], 35 | "react-hooks/exhaustive-deps": "warn", 36 | "semi": ["error", "always"] 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # These files are text and should be normalized (convert crlf -> lf) 2 | *.js text 3 | *.jsx text 4 | *.md text 5 | *.css text 6 | *.html text 7 | *.json text 8 | *.less text 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | *.pid.lock 11 | 12 | # Directory for instrumented libs generated by jscoverage/JSCover 13 | lib-cov 14 | 15 | # Coverage directory used by tools like istanbul 16 | coverage 17 | 18 | # nyc test coverage 19 | .nyc_output 20 | 21 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 22 | .grunt 23 | 24 | # node-waf configuration 25 | .lock-wscript 26 | 27 | # Compiled binary addons (http://nodejs.org/api/addons.html) 28 | build/Release 29 | 30 | # Dependency directories 31 | node_modules/ 32 | jspm_packages 33 | 34 | # Optional npm cache directory 35 | .npm 36 | 37 | # Optional eslint cache 38 | .eslintcache 39 | 40 | # Optional REPL history 41 | .node_repl_history 42 | 43 | # Output of 'npm pack' 44 | *.tgz 45 | 46 | #Openfin cache 47 | OpenFin/ 48 | 49 | #IDEs 50 | .idea 51 | .vscode 52 | .prettierc 53 | 54 | # Transpiled code 55 | dist 56 | build 57 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": true, 3 | "singleQuote": true, 4 | "trailingComma": "none", 5 | "bracketSpacing": true 6 | } 7 | -------------------------------------------------------------------------------- /INTERACTIONS.md: -------------------------------------------------------------------------------- 1 | # Interactions 2 | 3 | ## Components 4 | 5 | * Search Bar - The launchbar / hub of the Stockflux application. Allows users to spawn watchlists and charts as well as search for symbols to add to watchlists / charts. 6 | * Watchlist - Displays a list of favourited symbols 7 | * Chart - Displays historical trends (e.g. OHLC) for chosen symbol 8 | 9 | ## Channels 10 | 11 | * You can have upto six channels, with one chart per channel. 12 | * You're able to change a charts channel via a toggle above it. 13 | * Only one chart is allowed to have no channel, it being considered the 'default' chart. 14 | 15 | ## Search Bar Interactions 16 | 17 | * Clicking the watchlist icon focuses the currently active watchlist if it exists. Otherwise, it opens up a new watchlist with some defaulted symbols pre-added. 18 | * Clicking the chart icon focuses the current default chart if it exists. Otherwise, it opens up a new chart with a default symbol. 19 | * You can search for symbols via the input box. It'll list relevant actions for each symbol it finds 20 | * e.g. Add symbol to existing watchlist or chart. 21 | * You can add a symbol to an existing chart by picking a chart via its symbol, channel or both 22 | 23 | ## Watchlist Interactions 24 | * Clicking on the star icon unfavourites a watchlist item and removes it from the watchlist 25 | * Clicking on an watchlist item's action button allows the user to either 26 | * add that item's symbol to a new chart 27 | * add that items' symbol to an existing chart by picking it via its symbol, channel or both. 28 | 29 | ## Chart Interactions 30 | * Clicking on the channel toggle above the chart changes that chart's channel to the selected channel 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Scott Logic 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /assets/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/assets/.DS_Store -------------------------------------------------------------------------------- /assets/arrows/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/assets/arrows/.DS_Store -------------------------------------------------------------------------------- /assets/arrows/Price_Arrow_Down.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Arrow/Up Copy 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /assets/arrows/Price_Arrow_Up.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Arrow/Up 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /assets/arrows/Scroll_Arrow_Down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/assets/arrows/Scroll_Arrow_Down.png -------------------------------------------------------------------------------- /assets/arrows/Scroll_Arrow_Down.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Component/Scroll_Arrow_Down 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /assets/arrows/Scroll_Arrow_Up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/assets/arrows/Scroll_Arrow_Up.png -------------------------------------------------------------------------------- /assets/arrows/Scroll_Arrow_Up.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Component/Scroll_Arrow_Up Copy 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /assets/glyphs v1/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/assets/glyphs v1/.DS_Store -------------------------------------------------------------------------------- /assets/glyphs v1/24px/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/assets/glyphs v1/24px/.DS_Store -------------------------------------------------------------------------------- /assets/glyphs v1/24px/Glyph_Chart 24px.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Glyph/24Chart 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /assets/glyphs v1/24px/Glyph_Chart_Compressed.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /assets/glyphs v1/24px/Glyph_Left 24px.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Glyph/24Left 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /assets/glyphs v1/24px/Glyph_News 24px.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Glyph/24News 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /assets/glyphs v1/24px/Glyph_News_Compressed.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /assets/glyphs v1/24px/Glyph_Right 24px.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Glyph/24Right 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /assets/glyphs v1/24px/Glyph_Search 24px.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Glyph/24Search 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /assets/glyphs v1/24px/Glyph_Top 24px.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Glyph/24Top 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /assets/glyphs v1/24px/Glyph_Watchlist 24px.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Glyph/24Watchlist 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /assets/glyphs v1/24px/Glyph_Watchlist_Compressed.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /assets/glyphs v1/30px/Glyph_Chart 30px.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Glyph/Chart 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /assets/glyphs v1/30px/Glyph_Closesvg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Close 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /assets/glyphs v1/30px/Glyph_Drag 30px.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Glyph_Drag 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /assets/glyphs v1/30px/Glyph_Left 30px.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Glyph_Left 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /assets/glyphs v1/30px/Glyph_Minimize.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Minimize 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /assets/glyphs v1/30px/Glyph_News 30px.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Glyph_News 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /assets/glyphs v1/30px/Glyph_Right 30px.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Glyph_Right 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /assets/glyphs v1/30px/Glyph_Search 30px.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Glyph_Search 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /assets/glyphs v1/30px/Glyph_Top 30px.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Glyph_Top 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /assets/glyphs v1/30px/Glyph_Watchlist 30px.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Glyph_Watchlist 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /assets/icons v1/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/assets/icons v1/.DS_Store -------------------------------------------------------------------------------- /assets/icons v1/Icon_Link.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Icon_Link 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /assets/icons v1/Icon_Pin.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Icon_Pin 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /assets/logos/D3FC Logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /assets/specs/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/assets/specs/.DS_Store -------------------------------------------------------------------------------- /assets/specs/Specs.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/assets/specs/Specs.sketch -------------------------------------------------------------------------------- /communication-dependencies.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/communication-dependencies.PNG -------------------------------------------------------------------------------- /developer-proxy/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "developer-proxy", 3 | "version": "1.0.0", 4 | "main": "src/index.js", 5 | "scripts": { 6 | "start": "node ./src/index.js", 7 | "proxy": "nodemon ./src/index.js" 8 | }, 9 | "dependencies": { 10 | "cors": "^2.8.5", 11 | "deepmerge": "^4.2.2", 12 | "express": "^4.17.1", 13 | "node-fetch": "^2.6.0", 14 | "nodemon": "^2.0.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /developer-proxy/readMe.md: -------------------------------------------------------------------------------- 1 | # Developer Proxy 2 | 3 | Use of the developer proxy allows you to develop locally in reguards to each seperate app. This can be ran be using the command `npm run proxy`. 4 | 5 | # App Directory 6 | To modify the app directory to use the local proxy, modify the file `./src/static/apps.json` new stockflux or external apps can be added in for example this is the addition for a Giant Machines Watchlist 7 | ```json 8 | { 9 | "images": [], 10 | "intents": [ 11 | { 12 | "name": "WatchlistAdd" 13 | }, 14 | { 15 | "name": "WatchlistView" 16 | } 17 | ], 18 | "contactEmail": "contact@giantmachines.com", 19 | "manifest": "https://stockflux.scottlogic.com/api/apps/v1/giantmachines-watchlist/app.json", 20 | "manifestType": "openfin", 21 | "description": "Giant Machines Watchlist", 22 | "title": "Watchlist", 23 | "icons": [ 24 | { 25 | "icon": "https://stockflux.scottlogic.com/artifacts/giantmachines-watchlist/favicon.ico" 26 | }, 27 | { 28 | "icon": "https://stockflux.scottlogic.com/artifacts/giantmachines-watchlist/launcher.png" 29 | } 30 | ], 31 | "supportEmail": "contact@giantmachines.com", 32 | "customConfig": { 33 | "showInLauncher": true, 34 | "launcherIntent": "viewWatchlist" 35 | }, 36 | "appId": "giantmachines-watchlist", 37 | "name": "giantmachines-watchlist", 38 | "publisher": "Giant Machines" 39 | } 40 | ``` 41 | 42 | The `showInLauncher` value is the boolean option which allows a new option to appear in the Launcher bar. This needs to be set to `true`. 43 | `description` will be the text display which is shown in the launcher menu, and can be customised to change the menu option name. -------------------------------------------------------------------------------- /developer-proxy/src/config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | baseUrl: 'https://stockflux.scottlogic.com', 3 | port: 3010, 4 | overrides: { 5 | '/api/apps/v1/stockflux-watchlist': { 6 | manifest: 'http://localhost:3010/__static/watchlist.app.json' 7 | }, 8 | '/api/apps/v1/stockflux-news': { 9 | manifest: 'http://localhost:3010/__static/news.app.json' 10 | }, 11 | '/api/apps/v1/stockflux-chart': { 12 | manifest: 'http://localhost:3010/__static/chart.app.json' 13 | }, 14 | '/api/apps/v1': 'http://localhost:3010/__static/apps.json' 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /developer-proxy/src/index.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const express = require('express'); 3 | const cors = require('cors'); 4 | const config = require('./config'); 5 | const proxyOverride = require('./proxyOverride'); 6 | 7 | const { baseUrl, port = 3000 } = config; 8 | 9 | const app = express(); 10 | 11 | app.use(cors()); 12 | app.use('/__static', express.static(path.join(__dirname, './static'))); 13 | 14 | app.get('/**', proxyOverride(baseUrl)); 15 | 16 | // eslint-disable-next-line no-console 17 | app.listen(port, () => console.log(`Example app listening on port ${port}!`)); 18 | -------------------------------------------------------------------------------- /developer-proxy/src/proxyOverride.js: -------------------------------------------------------------------------------- 1 | const fetch = require('node-fetch'); 2 | const merge = require('deepmerge'); 3 | const config = require('./config'); 4 | 5 | module.exports = baseUrl => (req, res) => { 6 | const { method, path } = req; 7 | const { overrides = {} } = config; 8 | 9 | const options = { 10 | method, 11 | mode: 'no-cors', 12 | cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached 13 | headers: { 14 | 'Content-Type': 'application/json' 15 | }, 16 | redirect: 'follow' 17 | }; 18 | 19 | const url = baseUrl + path; 20 | const override = overrides[path]; 21 | 22 | if (path === '/api/apps/v1') { 23 | // eslint-disable-next-line no-console 24 | console.log(`Overriding path '${path}`); 25 | fetch(override, options) 26 | .then(proxyRes => { 27 | return proxyRes.json(); 28 | }) 29 | .then(proxyData => { 30 | res.send(proxyData); 31 | }) 32 | .catch(err => console.error('Proxy Error', err)); 33 | return; 34 | } 35 | 36 | // eslint-disable-next-line no-console 37 | console.log( 38 | override ? `Overriding path '${path}'` : `No overrides for path '${path}'` 39 | ); 40 | 41 | fetch(url, options) 42 | .then(proxyRes => { 43 | return proxyRes.json(); 44 | }) 45 | .then(proxyData => { 46 | if (override) { 47 | const overriddenData = merge(proxyData, overrides[path] || {}); 48 | res.json(overriddenData); 49 | } else { 50 | res.send(proxyData); // This helps handle non-overridden ones that are not JSON (aka news feeds) 51 | } 52 | }) 53 | .catch(err => console.error('Proxy Error', err)); 54 | }; 55 | -------------------------------------------------------------------------------- /developer-proxy/src/static/chart.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "runtime": { 3 | "arguments": "--enable-aggressive-domstorage-flushing", 4 | "version": "12.69.43.22" 5 | }, 6 | "startup_app": { 7 | "name": "stockflux-chart", 8 | "uuid": "33aa9062-9eb0-4875-b819-c90f38ef03eb", 9 | "url": "http://localhost:8051/index.html", 10 | "applicationIcon": "http://localhost:8051/favicon.ico", 11 | "autoShow": true, 12 | "defaultWidth": 850, 13 | "defaultHeight": 500, 14 | "minWidth": 850, 15 | "minHeight": 500, 16 | "defaultTop": 80, 17 | "saveWindowState": false, 18 | "frame": false, 19 | "contextMenu": true, 20 | "customData": { 21 | "apiBaseUrl": "http://localhost:3010/api" 22 | } 23 | }, 24 | "services": [ 25 | { 26 | "name": "layouts", 27 | "config": { 28 | "features": { 29 | "tab": false 30 | } 31 | } 32 | }, 33 | { 34 | "name": "fdc3" 35 | } 36 | ], 37 | "shortcut": { 38 | "company": "ScottLogic", 39 | "description": "Hosts StockFlux Chart as an OpenFin application.", 40 | "name": "StockFlux Chart", 41 | "icon": "http://localhost:8051/favicon.ico" 42 | }, 43 | "splashScreenImage": "http://localhost:8051/splashscreen.png" 44 | } -------------------------------------------------------------------------------- /developer-proxy/src/static/news.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "devtools_port": 9091, 3 | "runtime": { 4 | "arguments": "--enable-aggressive-domstorage-flushing", 5 | "version": "12.69.43.22" 6 | }, 7 | "startup_app": { 8 | "name": "stockflux-news", 9 | "uuid": "stockflux-news", 10 | "url": "http://localhost:8056/index.html", 11 | "applicationIcon": "http://localhost:8056/favicon.ico", 12 | "autoShow": true, 13 | "minHeight": 400, 14 | "defaultWidth": 400, 15 | "minWidth": 400, 16 | "maxWidth": 400, 17 | "defaultLeft": 90, 18 | "defaultTop": 90, 19 | "resizable": true, 20 | "saveWindowState": false, 21 | "frame": false, 22 | "contextMenu": true, 23 | "cornerRounding": { 24 | "height": 4, 25 | "width": 4 26 | }, 27 | "customData": { 28 | "apiBaseUrl": "http://localhost:3010/api" 29 | } 30 | }, 31 | "services": [ 32 | { 33 | "name": "layouts", 34 | "config": { 35 | "features": { 36 | "dock": true, 37 | "snap": true, 38 | "tab": false 39 | } 40 | } 41 | } 42 | ], 43 | "shortcut": { 44 | "company": "ScottLogic", 45 | "description": "Hosts StockFlux News as an OpenFin application.", 46 | "name": "StockFlux News", 47 | "icon": "http://localhost:8056/favicon.ico" 48 | }, 49 | "splashScreenImage": "http://localhost:8056/splashscreen.png" 50 | } -------------------------------------------------------------------------------- /developer-proxy/src/static/watchlist.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "devtools_port": 9090, 3 | "runtime": { 4 | "arguments": "--enable-aggressive-domstorage-flushing", 5 | "version": "12.69.43.22" 6 | }, 7 | "startup_app": { 8 | "name": "stockflux-watchlist", 9 | "uuid": "33aa9062-9eb0-4875-b819-c90f38ef0999", 10 | "url": "http://localhost:8052/index.html", 11 | "applicationIcon": "http://localhost:8052/favicon.ico", 12 | "autoShow": true, 13 | "defaultWidth": 271, 14 | "defaultHeight": 600, 15 | "maxWidth": 271, 16 | "minWidth": 271, 17 | "minHeight": 300, 18 | "defaultLeft": 90, 19 | "defaultTop": 90, 20 | "frame": false, 21 | "contextMenu": true, 22 | "customData": { 23 | "apiBaseUrl": "http://localhost:3010/api" 24 | } 25 | }, 26 | "services": [ 27 | { 28 | "name": "layouts", 29 | "config": { 30 | "features": { 31 | "tab": false, 32 | "dock": false, 33 | "snap": false 34 | } 35 | } 36 | } 37 | ], 38 | "shortcut": { 39 | "company": "ScottLogic", 40 | "description": "Hosts StockFlux Watchlist as an OpenFin application.", 41 | "name": "StockFlux Watchlist", 42 | "icon": "http://localhost:8052/favicon.ico" 43 | }, 44 | "splashScreenImage": "http://localhost:8052/splashscreen.png" 45 | } -------------------------------------------------------------------------------- /kill.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | taskkill/F /IM openfin.exe 4 | taskkill /IM node.exe /F 5 | 6 | del /q "%localappdata%\OpenFin\cache\*" 7 | FOR /D %%p IN ("%localappdata%\OpenFin\cache\*.*") DO rmdir "%%p" /s /q 8 | 9 | del /q "%localappdata%\OpenFin\apps\*" 10 | FOR /D %%p IN ("%localappdata%\OpenFin\apps\*.*") DO rmdir "%%p" /s /q 11 | 12 | del /q "%localappdata%\OpenFin\runtime\*" 13 | FOR /D %%p IN ("%localappdata%\OpenFin\runtime\*.*") DO rmdir "%%p" /s /q 14 | 15 | del /q "%localappdata%\OpenFin\logs\*" 16 | FOR /D %%p IN ("%localappdata%\OpenFin\logs\*.*") DO rmdir "%%p" /s /q 17 | 18 | del /q "%localappdata%\OpenFin\cache.dat" 19 | 20 | del /q "%localappdata%\OpenFin\OpenFinRVM.exe" 21 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "packages": [ 3 | "packages/*" 4 | ], 5 | "version": "0.0.0" 6 | } 7 | -------------------------------------------------------------------------------- /package-dependencies.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/package-dependencies.PNG -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "stockflux", 3 | "version": "13.1.1", 4 | "license": "MIT", 5 | "devDependencies": { 6 | "babel-eslint": "10.0.1", 7 | "concurrently": "^4.1.2", 8 | "eslint": "^5.16.0", 9 | "eslint-config-prettier": "^6.3.0", 10 | "eslint-config-react-app": "^5.0.1", 11 | "eslint-plugin-flowtype": "^4.3.0", 12 | "eslint-plugin-import": "^2.18.2", 13 | "eslint-plugin-jsx-a11y": "^6.2.3", 14 | "eslint-plugin-prettier": "^3.1.0", 15 | "eslint-plugin-react": "^7.14.3", 16 | "eslint-plugin-react-hooks": "^2.0.1", 17 | "lerna": "^3.16.4", 18 | "prettier": "^1.18.2" 19 | }, 20 | "scripts": { 21 | "bootstrap": "lerna bootstrap --concurrency 1", 22 | "build": "lerna run build", 23 | "lint": "./node_modules/.bin/eslint \"**/*.js\" --ignore-pattern node_modules/ --ignore-pattern build/ --ignore-pattern dist/ --ignore-pattern serviceWorker.js", 24 | "lint-fix": "npm run lint -- --fix", 25 | "chart:start": "cd packages/stockflux-chart && npm run start", 26 | "container:start": "cd packages/stockflux-container && npm run start", 27 | "launcher:start": "cd packages/stockflux-launcher && npm run start", 28 | "news:start": "cd packages/stockflux-news && npm run start", 29 | "watchlist:start": "cd packages/stockflux-watchlist && npm run start", 30 | "all:start": "concurrently \"npm run chart:start\" \"npm run container:start\" \"npm run launcher:start\" \"npm run news:start\" \"npm run watchlist:start\"", 31 | "chart:launch": "cd packages/stockflux-chart && npm run launch", 32 | "launcher:launch": "cd packages/stockflux-launcher && npm run launch", 33 | "news:launch": "cd packages/stockflux-news && npm run launch", 34 | "watchlist:launch": "cd packages/stockflux-watchlist && npm run launch", 35 | "chart:launch-appd": "cd packages/stockflux-chart && npm run launch-appd", 36 | "launcher:launch-appd": "cd packages/stockflux-launcher && npm run launch-appd", 37 | "news:launch-appd": "cd packages/stockflux-news && npm run launch-appd", 38 | "watchlist:launch-appd": "cd packages/stockflux-watchlist && npm run launch-appd", 39 | "proxy:build": "cd developer-proxy && npm i", 40 | "proxy:start": "cd developer-proxy && npm run start" 41 | }, 42 | "dependencies": {} 43 | } 44 | -------------------------------------------------------------------------------- /packages/stockflux-chart/README.md: -------------------------------------------------------------------------------- 1 | ## StockFlux Chart 2 | 3 | StockFlux Chart is a part of StockFlux app suite intended to work with StockFlux Launcher, Watchlist, and News apps. 4 | Chart is an application designed to provide an interactive view of a symbol's OHLC(Open, High, Low and Close) data over the last 5 years. 5 | 6 | ### Launching StockFlux Chart app from the installer 7 | 8 | Download the [installer](https://install.openfin.co/download/?os=win&config=https%3A%2F%2Fstockflux.scottlogic.com%2Fapi%2Fapps%2Fv1%2Fstockflux-launcher%2Fapp.json&fileName=stockflux&unzipped=true). After installing `StockFlux Launcher` icon should appear on the desktop. Double click it to open the StockFlux Launcher. 9 | 10 | StockFlux Chart can be launched from the launcher app: 11 | 12 | - by clicking on StockFlux Chart app icon in the top left corner of the launcher 13 | - by searching for a symbol using launcher's input field. When the list of symbols loads, click on the chart icon of a particular symbol and the chart application will be launched. 14 | 15 | ### Chart functionality 16 | 17 | The user can view data over the period of 5 years. The chart allows the user to zoom in on a period of time for a more focused view. Overlays can be toggled on and off to provide extra information about the OHLC data. By default the OHLC is displayed by a series of candles, this can be changed by the user. 18 | 19 | ### Running locally 20 | 21 | In order to launch the StockFlux Chart app locally, StockFlux Core, StockFlux Components and Stockflux Bitflux have to be built first. 22 | Run the following commands in the root package to make lerna do the heavy lifting for you: 23 | 24 | ```bash 25 | npm install 26 | npm run bootstrap 27 | npm run build 28 | ``` 29 | 30 | To start and launch the StockFlux Chart: 31 | 32 | ```bash 33 | npm start 34 | npm run launch 35 | ``` 36 | 37 | If no symbol is provided from the Openfin context generated data is shown. 38 | 39 | To launch other StockFlux apps locally read the `README.md` files in the project folders. 40 | -------------------------------------------------------------------------------- /packages/stockflux-chart/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "stockflux-chart", 3 | "version": "13.1.1", 4 | "private": true, 5 | "dependencies": { 6 | "bootstrap": "^3.3.6", 7 | "classnames": "^2.2.6", 8 | "d3": "^5.15.0", 9 | "d3fc": "^14.1.21", 10 | "date-fns": "1.30.1", 11 | "openfin-fdc3": "^0.1.1", 12 | "openfin-layouts": "^1.0.0", 13 | "openfin-react-hooks": "^1.3.3", 14 | "react": "^16.8.6", 15 | "react-dom": "^16.8.6", 16 | "react-icons": "^3.7.0", 17 | "react-scripts": "3.0.1", 18 | "stockflux-components": "13.1.1", 19 | "stockflux-core": "13.1.1", 20 | "throat": "^4.1.0" 21 | }, 22 | "homepage": "./", 23 | "scripts": { 24 | "start": "cross-env BROWSER=none PORT=8051 react-scripts start", 25 | "launch": "openfin --launch --config ./public/app.dev.json", 26 | "launch-appd": "openfin --launch --config http://localhost:3000/api/apps/v1/stockflux-chart/app.json", 27 | "build": "react-scripts build", 28 | "test": "react-scripts test", 29 | "eject": "react-scripts eject" 30 | }, 31 | "browserslist": [ 32 | ">0.2%", 33 | "not dead", 34 | "not ie <= 11", 35 | "not op_mini all" 36 | ], 37 | "devDependencies": { 38 | "cross-env": "^5.2.0", 39 | "openfin-cli": "^2.0.8" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /packages/stockflux-chart/public/app.dev.json: -------------------------------------------------------------------------------- 1 | { 2 | "runtime": { 3 | "arguments": "--enable-aggressive-domstorage-flushing", 4 | "version": "12.69.43.22" 5 | }, 6 | "startup_app": { 7 | "name": "stockflux-chart", 8 | "uuid": "33aa9062-9eb0-4875-b819-c90f38ef03eb", 9 | "url": "http://localhost:8051/index.html", 10 | "applicationIcon": "http://localhost:8051/favicon.ico", 11 | "autoShow": true, 12 | "defaultWidth": 850, 13 | "defaultHeight": 500, 14 | "minWidth": 850, 15 | "minHeight": 500, 16 | "defaultTop": 80, 17 | "saveWindowState": false, 18 | "frame": false, 19 | "contextMenu": true, 20 | "customData": { 21 | "apiBaseUrl": "http://localhost:3010/api" 22 | } 23 | }, 24 | "services": [ 25 | { 26 | "name": "layouts", 27 | "config": { 28 | "features": { 29 | "tab": false 30 | } 31 | } 32 | }, 33 | { 34 | "name": "fdc3" 35 | } 36 | ], 37 | "shortcut": { 38 | "company": "ScottLogic", 39 | "description": "Hosts StockFlux Chart as an OpenFin application.", 40 | "name": "StockFlux Chart", 41 | "icon": "http://localhost:8051/favicon.ico" 42 | }, 43 | "splashScreenImage": "http://localhost:8051/splashscreen.png" 44 | } -------------------------------------------------------------------------------- /packages/stockflux-chart/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/packages/stockflux-chart/public/favicon.ico -------------------------------------------------------------------------------- /packages/stockflux-chart/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | StockFlux - Chart 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /packages/stockflux-chart/public/launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/packages/stockflux-chart/public/launcher.png -------------------------------------------------------------------------------- /packages/stockflux-chart/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "StockFlux Watchlist", 3 | "name": "StockFlux Chart App", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": ".", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /packages/stockflux-chart/public/splashscreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/packages/stockflux-chart/public/splashscreen.png -------------------------------------------------------------------------------- /packages/stockflux-chart/src/assets/d3fc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/stockflux-chart/src/assets/png/close_indicator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/packages/stockflux-chart/src/assets/png/close_indicator.png -------------------------------------------------------------------------------- /packages/stockflux-chart/src/components/chart.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | overflow-x: hidden; 4 | overflow-y: hidden; 5 | background: var(--primary-dark-blue); 6 | color: var(--text-color); 7 | } 8 | .gridline-y { 9 | stroke: var(--chart-gridline); 10 | stroke-width: 0.5px; 11 | stroke-opacity: 0.75; 12 | } 13 | 14 | .gridline-x { 15 | stroke: var(--chart-gridline); 16 | stroke-width: 0.5px; 17 | stroke-opacity: 0.75; 18 | } 19 | 20 | .candlestick.down { 21 | fill: var(--chart-candlestick-down); 22 | stroke: var(--chart-candlestick-down); 23 | } 24 | .candlestick.up { 25 | fill: var(--chart-candlestick-up); 26 | stroke: var(--chart-candlestick-up); 27 | } 28 | 29 | .chart-content { 30 | height: calc(100vh - 65px); 31 | width: 100%; 32 | } 33 | 34 | .handle.handle--w { 35 | width: 0.3%; 36 | fill: var(--chart-handle); 37 | transform: translateX(3px); 38 | } 39 | 40 | .handle.handle--e { 41 | width: 0.3%; 42 | fill: var(--chart-handle); 43 | } 44 | 45 | .selection { 46 | stroke: none; 47 | fill: var(--chart-brush-selection); 48 | fill-opacity: 0.2; 49 | } 50 | 51 | .domain { 52 | stroke: var(--chart-domain); 53 | stroke-width: 0.5; 54 | } 55 | 56 | .tick text { 57 | fill: var(--chart-domain); 58 | } 59 | 60 | .tick path { 61 | stroke: var(--chart-tick-path); 62 | stroke-width: 0.5; 63 | } 64 | 65 | .secondary-x-axis .tick line { 66 | stroke-width: 1; 67 | stroke: var(--chart-domain); 68 | } 69 | 70 | .secondary-x-axis .domain { 71 | stroke-width: 0; 72 | } 73 | 74 | #legend-container { 75 | position: absolute; 76 | top: 35vh; 77 | left: -25px; 78 | } 79 | 80 | #legend-container text { 81 | color: var(--text-color); 82 | } 83 | 84 | .legend-label { 85 | fill: var(--text-color); 86 | font-weight: var(--font-weight-bold); 87 | } 88 | 89 | .legend-value { 90 | fill: var(--text-color); 91 | font-weight: var(--font-weight-bold); 92 | } 93 | -------------------------------------------------------------------------------- /packages/stockflux-chart/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import { OpenfinApiHelpers } from 'stockflux-core'; 4 | import App from './App'; 5 | 6 | const mountApp = () => { 7 | ReactDOM.render(, document.getElementById('root')); 8 | }; 9 | 10 | if (OpenfinApiHelpers.getWindow()) { 11 | mountApp(); 12 | } else { 13 | console.error('This application can only be run in an OpenFin container.'); 14 | } 15 | -------------------------------------------------------------------------------- /packages/stockflux-chart/src/reducers/open-apps/Action.js: -------------------------------------------------------------------------------- 1 | export default { 2 | SET_WATCHLIST_WINDOW: 'SET_WATCHLIST_WINDOW', 3 | SET_ADD_TO_WATCHLIST: 'SET_ADD_TO_WATCHLIST', 4 | SET_NEWS_WINDOW: 'SET_NEWS_WINDOW', 5 | RESET: 'RESET' 6 | }; 7 | -------------------------------------------------------------------------------- /packages/stockflux-chart/src/reducers/open-apps/OpenApps.js: -------------------------------------------------------------------------------- 1 | import ActionType from './Action'; 2 | 3 | export const initialState = { 4 | watchlist: false, 5 | addToWatchlist: false, 6 | news: false 7 | }; 8 | 9 | export default (state, { type, payload }) => { 10 | switch (type) { 11 | case ActionType.SET_WATCHLIST_WINDOW: 12 | return { 13 | ...state, 14 | watchlist: payload 15 | }; 16 | case ActionType.SET_NEWS_WINDOW: 17 | return { 18 | ...state, 19 | news: payload 20 | }; 21 | case ActionType.RESET: 22 | return initialState; 23 | default: 24 | throw new Error(); 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /packages/stockflux-components/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "@babel/preset-react" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /packages/stockflux-components/README.md: -------------------------------------------------------------------------------- 1 | ## StockFlux Components 2 | 3 | StockFlux Components is a part of the StockFlux application suite. It is a library of shared components used by the core set of applications. 4 | 5 | ### Install 6 | 7 | Currently the library is used locally across the other Stockflux applications. 8 | 9 | Before you run an application that has the components library as a dependency you must build the components. To do so run the following command in the Stockflux-components directory: 10 | 11 | ```bash 12 | npm install 13 | npm run build 14 | ``` 15 | 16 | It is added as a dependency in the target applications `package.json` like so: 17 | 18 | ```json 19 | "dependencies": { 20 | "stockflux-components": "file:../stockflux-components", 21 | } 22 | ``` 23 | 24 | ### Usage 25 | 26 | The components export is comprised of 4 components and 3 svg components. 27 | 28 | ```javascript 29 | export default { 30 | Titlebar, 31 | ScrollWrapperY, 32 | Spinner, 33 | LargeSpinner, 34 | // svgs 35 | News, 36 | Chart, 37 | Watchlist 38 | }; 39 | ``` 40 | 41 | ```javascript 42 | import Components from 'stockflux-components'; 43 | ``` 44 | 45 | The global default export is defined as `Components`. You can use it like so: 46 | 47 | ```jsx 48 | 49 | 50 | 51 | 52 | ``` 53 | -------------------------------------------------------------------------------- /packages/stockflux-components/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "stockflux-components", 3 | "version": "13.1.1", 4 | "private": true, 5 | "main": "./dist/index.js", 6 | "devDependencies": { 7 | "@babel/cli": "^7.5.5", 8 | "@babel/core": "^7.5.5", 9 | "@babel/preset-react": "^7.0.0", 10 | "babel-loader": "^8.0.6", 11 | "css-loader": "^2.1.1", 12 | "date-fns": "^1.30.1", 13 | "openfin-fdc3": "^0.1.1", 14 | "stockflux-core": "13.1.1", 15 | "style-loader": "^0.23.1", 16 | "url-loader": "^1.1.2", 17 | "webpack": "^4.39.3", 18 | "webpack-cli": "^3.3.8" 19 | }, 20 | "peerDependencies": { 21 | "react": "^16.8.6", 22 | "openfin-react-hooks": "^1.3.3" 23 | }, 24 | "scripts": { 25 | "build": "webpack" 26 | }, 27 | "dependencies": { 28 | "classnames": "^2.2.6", 29 | "openfin-react-hooks": "^1.3.3", 30 | "react-icons": "^3.7.0", 31 | "react-svg-loader": "^3.0.3" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/stockflux-components/src/components/Titlebar/Titlebar.css: -------------------------------------------------------------------------------- 1 | .titlebar-container { 2 | -webkit-app-region: drag; 3 | display: flex; 4 | flex-direction: row; 5 | height: var(--titlebar-height); 6 | background-color: var(--window-header-bar); 7 | align-items: stretch; 8 | } 9 | 10 | .titlebar-container > .title-container { 11 | flex-grow: 1; 12 | margin-top: 5px 13 | } 14 | 15 | .title-container > span { 16 | font-family: var(--font-roboto-sans-serif); 17 | font-size: var(--font-large); 18 | margin-left: 8px; 19 | } 20 | 21 | .titlebar-container > .icons-container { 22 | display: flex; 23 | align-items: center; 24 | flex-grow: 0; 25 | -webkit-app-region: no-drag; 26 | justify-content: space-evenly; 27 | } 28 | 29 | .titlebar-container > .icons-container > .button-icon { 30 | height: 15px; 31 | } 32 | 33 | .header-icon { 34 | cursor: pointer; 35 | } 36 | 37 | .header-icon:hover { 38 | background-color: var(--icon-hover-light); 39 | } 40 | 41 | .header-icon > svg > * { 42 | fill: var(--header-icon); 43 | } 44 | 45 | .link-icon > svg > * { 46 | color: var(--icon-active); 47 | } -------------------------------------------------------------------------------- /packages/stockflux-components/src/components/Titlebar/Titlebar.js: -------------------------------------------------------------------------------- 1 | import React, { useCallback } from 'react'; 2 | import { useDocked } from 'openfin-react-hooks'; 3 | import { snapAndDock } from 'openfin-layouts'; 4 | import { OpenfinApiHelpers } from 'stockflux-core'; 5 | import CloseIcon from '../icons/close.svg'; 6 | import MinimizeIcon from '../icons/minimize.svg'; 7 | import LinkIcon from '../icons/link.svg'; 8 | import ConfirmationWindow from '../popups/ConfirmationWindow'; 9 | 10 | import './Titlebar.css'; 11 | 12 | export default ({ title, confirmClose }) => { 13 | const isDocked = useDocked(); 14 | 15 | const onMinimizeClick = useCallback(async () => { 16 | const currentWindow = await OpenfinApiHelpers.getCurrentWindow(); 17 | currentWindow.minimize(); 18 | }, []); 19 | 20 | const onCloseClick = useCallback(async () => { 21 | const currentWindow = await OpenfinApiHelpers.getCurrentWindow(); 22 | currentWindow.close(); 23 | }, []); 24 | 25 | const onUndockClick = useCallback(async () => { 26 | await snapAndDock.undockWindow(); 27 | }, []); 28 | 29 | return ( 30 |
31 |
32 | {title} 33 |
34 |
35 | {isDocked[0] && ( 36 |
41 | 42 |
43 | )} 44 |
45 | 46 |
47 | {!confirmClose && ( 48 |
49 | 50 |
51 | )} 52 | {confirmClose && ( 53 | 57 |
58 | 59 |
60 |
61 | )} 62 |
63 |
64 | ); 65 | }; 66 | -------------------------------------------------------------------------------- /packages/stockflux-components/src/components/buttons/borderless-button/BorderlessButton.css: -------------------------------------------------------------------------------- 1 | .borderless { 2 | display: inline-block; 3 | color: var(--text-color); 4 | fill: var(--text-color); 5 | border: none; 6 | outline: none; 7 | background-color: inherit; 8 | cursor: pointer; 9 | } 10 | 11 | .borderless:hover { 12 | color: var(--text-teal-light); 13 | } 14 | 15 | .borderless svg { 16 | margin: auto; 17 | display: block; 18 | shape-rendering: auto; 19 | fill: currentColor; 20 | stroke: none; 21 | } 22 | 23 | .borderless:active { 24 | fill: var(--icon-active); 25 | } 26 | 27 | .borderless:disabled { 28 | color: var(--color-inactive); 29 | fill: var(--color-inactive); 30 | cursor: default; 31 | } 32 | -------------------------------------------------------------------------------- /packages/stockflux-components/src/components/buttons/borderless-button/BorderlessButton.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import cx from 'classnames'; 3 | import './BorderlessButton.css'; 4 | 5 | export default ({ children, small, className, onClick, disabled }) => ( 6 | 13 | ); 14 | -------------------------------------------------------------------------------- /packages/stockflux-components/src/components/buttons/borderless-buttons/Close.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { FaTimes } from 'react-icons/fa'; 3 | import cx from 'classnames'; 4 | import BorderlessButton from '../borderless-button/BorderlessButton'; 5 | 6 | export default props => ( 7 | 11 | 12 | 13 | ); 14 | -------------------------------------------------------------------------------- /packages/stockflux-components/src/components/buttons/borderless-buttons/app-shortcuts/Chart.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Launchers } from 'stockflux-core'; 3 | import ChartIconSmall from '../../../glyphs/small/chart.svg'; 4 | import ChartIcon from '../../../glyphs/launcher/chart.svg'; 5 | import RoundButton from '../../round-button/RoundButton'; 6 | 7 | export default ({ symbol, name, small, disabled, onClick, intentsEnabled }) => { 8 | if (small) { 9 | return ( 10 | Launchers.launchChart(symbol, name, intentsEnabled)} 13 | disabled={disabled} 14 | small={small} 15 | > 16 | 17 | 18 | ); 19 | } else 20 | return ( 21 | { 24 | await Launchers.launchChart(symbol, name, intentsEnabled); 25 | if (onClick) onClick(); 26 | }} 27 | disabled={disabled} 28 | small={small} 29 | > 30 | 31 | 32 | ); 33 | }; 34 | -------------------------------------------------------------------------------- /packages/stockflux-components/src/components/buttons/borderless-buttons/app-shortcuts/External.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Launchers } from 'stockflux-core'; 3 | import RoundButton from '../../round-button/RoundButton'; 4 | 5 | export default ({ manifest }) => { 6 | return ( 7 | Launchers.launchChildWindow(manifest)} 10 | > 11 | {manifest.description} 12 | 13 | ); 14 | }; 15 | -------------------------------------------------------------------------------- /packages/stockflux-components/src/components/buttons/borderless-buttons/app-shortcuts/News.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Launchers } from 'stockflux-core'; 3 | import NewsIconSmall from '../../../glyphs/small/news.svg'; 4 | import NewsIcon from '../../../glyphs/launcher/news.svg'; 5 | import RoundButton from '../../round-button/RoundButton'; 6 | 7 | export default ({ symbol, name, small, disabled, intentsEnabled }) => { 8 | if (small) { 9 | return ( 10 | Launchers.launchNews(symbol, name, intentsEnabled)} 13 | disabled={disabled} 14 | small={small} 15 | > 16 | 17 | 18 | ); 19 | } else 20 | return ( 21 | Launchers.launchNews(symbol, name, intentsEnabled)} 24 | disabled={disabled} 25 | small={small} 26 | > 27 | 28 | 29 | ); 30 | }; 31 | -------------------------------------------------------------------------------- /packages/stockflux-components/src/components/buttons/borderless-buttons/app-shortcuts/Watchlist.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Launchers } from 'stockflux-core'; 3 | import WatchlistIconSmall from '../../../glyphs/small/watchlist.svg'; 4 | import WatchlistIcon from '../../../glyphs/launcher/watchlist.svg'; 5 | import RoundButton from '../../round-button/RoundButton'; 6 | 7 | export default ({ symbol, name, small, disabled, intentsEnabled, title }) => { 8 | if (small) { 9 | return ( 10 | Launchers.launchWatchlist(symbol, name, intentsEnabled)} 13 | disabled={disabled} 14 | small={small} 15 | > 16 | 17 | 18 | ); 19 | } else 20 | return ( 21 | Launchers.launchWatchlist(symbol, name, intentsEnabled)} 24 | disabled={disabled} 25 | small={small} 26 | > 27 | 28 | {title} 29 | 30 | ); 31 | }; 32 | -------------------------------------------------------------------------------- /packages/stockflux-components/src/components/buttons/dialog-button/DialogButton.css: -------------------------------------------------------------------------------- 1 | .dialog { 2 | display: inline-block; 3 | color: var(--text-color); 4 | border: none; 5 | outline: none; 6 | background-color: inherit; 7 | cursor: pointer; 8 | } 9 | 10 | .dialog.small { 11 | height: 30px; 12 | width: 30px; 13 | padding: 5px; 14 | margin: 2px; 15 | } 16 | 17 | .dialog:hover { 18 | background-color: var(--color-highlight-hover); 19 | } 20 | 21 | .dialog:active { 22 | background-color: var(--color-highlight-hover); 23 | } 24 | 25 | .dialog:disabled { 26 | color: var(--color-inactive); 27 | cursor: default; 28 | } 29 | 30 | .dialog:disabled:hover { 31 | background-color: inherit; 32 | } -------------------------------------------------------------------------------- /packages/stockflux-components/src/components/buttons/dialog-button/DialogButton.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import cx from 'classnames'; 3 | import './DialogButton.css'; 4 | 5 | export default ({ children, small, className, onClick, disabled }) => ( 6 | 13 | ); 14 | -------------------------------------------------------------------------------- /packages/stockflux-components/src/components/buttons/round-button/RoundButton.css: -------------------------------------------------------------------------------- 1 | .round { 2 | display: inline-block; 3 | color: var(--icon-inactive); 4 | border: none; 5 | outline: none; 6 | background-color: inherit; 7 | cursor: pointer; 8 | } 9 | 10 | .round.small { 11 | height: 30px; 12 | width: 30px; 13 | padding: 5px; 14 | margin: 2px; 15 | } 16 | 17 | .round svg { 18 | display: block; 19 | shape-rendering: auto; 20 | fill: currentColor; 21 | } 22 | 23 | .round svg:hover { 24 | color: inherit; 25 | } 26 | 27 | .round:hover { 28 | color: var(--icon-active); 29 | } 30 | 31 | .round:active { 32 | background-color: var(--middle-background-lighter); 33 | } 34 | 35 | .round:disabled { 36 | color: var(--light-background); 37 | cursor: default; 38 | } 39 | 40 | .round:disabled:hover { 41 | background-color: inherit; 42 | } 43 | 44 | .round:not(:disabled):active { 45 | background-color: var(--middle-background-lighter); 46 | } 47 | 48 | .external { 49 | width: 76px; 50 | height:62px; 51 | overflow: hidden; 52 | } -------------------------------------------------------------------------------- /packages/stockflux-components/src/components/buttons/round-button/RoundButton.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import cx from 'classnames'; 3 | import './RoundButton.css'; 4 | 5 | export default ({ children, small, className, onClick, disabled }) => ( 6 | 13 | ); 14 | -------------------------------------------------------------------------------- /packages/stockflux-components/src/components/glyphs/arrows/priceArrowDown.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /packages/stockflux-components/src/components/glyphs/arrows/priceArrowUp.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /packages/stockflux-components/src/components/glyphs/launcher/left.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /packages/stockflux-components/src/components/glyphs/launcher/right.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /packages/stockflux-components/src/components/glyphs/launcher/search.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /packages/stockflux-components/src/components/glyphs/launcher/top.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /packages/stockflux-components/src/components/glyphs/launcher/watchlist.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/stockflux-components/src/components/glyphs/normal/chart.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /packages/stockflux-components/src/components/glyphs/normal/watchlist.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/stockflux-components/src/components/glyphs/small/chart.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /packages/stockflux-components/src/components/glyphs/small/hide.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /packages/stockflux-components/src/components/glyphs/small/remove.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /packages/stockflux-components/src/components/glyphs/small/reveal.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /packages/stockflux-components/src/components/glyphs/small/watchlist.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/stockflux-components/src/components/icons/chart.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/stockflux-components/src/components/icons/close.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/stockflux-components/src/components/icons/link.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /packages/stockflux-components/src/components/icons/minimize.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /packages/stockflux-components/src/components/icons/news.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/stockflux-components/src/components/icons/watchlist.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/stockflux-components/src/components/popups/ConfirmationWindow.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PopupWindow from './PopupWindow'; 3 | 4 | const ConfirmationWindow = ({ message, onConfirm, onReject, children }) => { 5 | const modalOptions = [ 6 | { 7 | name: 'Cancel', 8 | icon: 'No', 9 | className: 'modal-cancel', 10 | action: onReject 11 | }, 12 | { 13 | name: 'Confirm', 14 | action: onConfirm, 15 | icon: 'Yes', 16 | className: 'modal-confirm' 17 | } 18 | ]; 19 | 20 | return ( 21 | 22 | {children} 23 | 24 | ); 25 | }; 26 | 27 | export default ConfirmationWindow; 28 | -------------------------------------------------------------------------------- /packages/stockflux-components/src/components/scroll-wrapper-y/ScrollWrapperY.css: -------------------------------------------------------------------------------- 1 | .scrollWrapperY { 2 | flex: 1 1 auto; 3 | position: relative; 4 | overflow-x: hidden; 5 | height: inherit; 6 | overflow-y: overlay !important; 7 | margin-right: 0 !important; 8 | } 9 | -------------------------------------------------------------------------------- /packages/stockflux-components/src/components/scroll-wrapper-y/ScrollWrapperY.js: -------------------------------------------------------------------------------- 1 | import React, { useRef, useEffect } from 'react'; 2 | import './ScrollWrapperY.css'; 3 | 4 | const ScrollWrapperY = ({ children }) => { 5 | const scrollWrapperRef = useRef(null); 6 | 7 | useEffect(() => { 8 | checkIfOverflowing(); 9 | window.addEventListener('resize', checkIfOverflowing); 10 | return () => { 11 | window.removeEventListener('resize', checkIfOverflowing); 12 | }; 13 | }, []); 14 | 15 | const checkIfOverflowing = () => { 16 | const domElement = scrollWrapperRef.current; 17 | if (domElement) 18 | domElement.classList.toggle( 19 | 'scrollPaddingRight', 20 | domElement.scrollHeight > domElement.clientHeight 21 | ); 22 | }; 23 | 24 | useEffect(checkIfOverflowing); 25 | 26 | return ( 27 |
28 | {children} 29 |
30 | ); 31 | }; 32 | export default ScrollWrapperY; 33 | -------------------------------------------------------------------------------- /packages/stockflux-components/src/components/spinner/Spinner.css: -------------------------------------------------------------------------------- 1 | .spinner { 2 | --white-spinner: #fff; 3 | --spinner-size: 30px; 4 | --spinner-thickness: 5px; 5 | --spinner-animation-duration: 0.6s; 6 | --low-opacity-white-border: rgba(255, 255, 255, 0.2); 7 | 8 | --generic-spinner-border: var(--spinner-thickness) solid var(--low-opacity-white-border); 9 | 10 | border-top: var(--generic-spinner-border); 11 | border-right: var(--generic-spinner-border); 12 | border-bottom: var(--generic-spinner-border); 13 | border-left: var(--spinner-thickness) solid var(--white-spinner); 14 | transform: translateZ(0); 15 | animation: spin var(--spinner-animation-duration) infinite linear; 16 | border-radius: 50%; 17 | width: var(--spinner-size); 18 | height: var(--spinner-size); 19 | margin: auto; 20 | } 21 | 22 | @keyframes spin { 23 | 0% { 24 | -webkit-transform: rotate(0deg); 25 | transform: rotate(0deg); 26 | } 27 | 28 | 100% { 29 | -webkit-transform: rotate(360deg); 30 | transform: rotate(360deg); 31 | } 32 | } 33 | 34 | .spinner.large { 35 | --spinner-size: 50px; 36 | --spinner-thickness: 7px; 37 | } -------------------------------------------------------------------------------- /packages/stockflux-components/src/components/spinner/Spinner.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import './Spinner.css'; 3 | 4 | export const Spinner = () => { 5 | return
; 6 | }; 7 | export const LargeSpinner = () => { 8 | return
; 9 | }; 10 | -------------------------------------------------------------------------------- /packages/stockflux-components/src/images/arrow_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/packages/stockflux-components/src/images/arrow_down.png -------------------------------------------------------------------------------- /packages/stockflux-components/src/images/arrow_up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/packages/stockflux-components/src/images/arrow_up.png -------------------------------------------------------------------------------- /packages/stockflux-components/src/images/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/packages/stockflux-components/src/images/close.png -------------------------------------------------------------------------------- /packages/stockflux-components/src/images/close_active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/packages/stockflux-components/src/images/close_active.png -------------------------------------------------------------------------------- /packages/stockflux-components/src/images/close_indicator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/packages/stockflux-components/src/images/close_indicator.png -------------------------------------------------------------------------------- /packages/stockflux-components/src/images/compact.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/packages/stockflux-components/src/images/compact.png -------------------------------------------------------------------------------- /packages/stockflux-components/src/images/compact_active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/packages/stockflux-components/src/images/compact_active.png -------------------------------------------------------------------------------- /packages/stockflux-components/src/images/full_view.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/packages/stockflux-components/src/images/full_view.png -------------------------------------------------------------------------------- /packages/stockflux-components/src/images/full_view_active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/packages/stockflux-components/src/images/full_view_active.png -------------------------------------------------------------------------------- /packages/stockflux-components/src/images/index.js: -------------------------------------------------------------------------------- 1 | import ArrowDown from './arrow_down.png'; 2 | import ArrowUp from './arrow_up.png'; 3 | import CloseActive from './close_active.png'; 4 | import CloseIndicator from './close_indicator.png'; 5 | import Close from './close.png'; 6 | import CompactActive from './compact_active.png'; 7 | import Compact from './compact.png'; 8 | import StarHover from './star_hover.png'; 9 | import StarOffHover from './star_off_hover.png'; 10 | import StarOff from './star_off.png'; 11 | import StarOn from './star_on.png'; 12 | import FullViewActive from './full_view_active.png'; 13 | import FullView from './full_view.png'; 14 | import MaximizeActive from './maximize_active.png'; 15 | import Maximize from './maximize.png'; 16 | import MinimizeActive from './minimize_active.png'; 17 | import Minimize from './minimize.png'; 18 | import NoStarred from './no_starred.png'; 19 | import NormalSizeActive from './normal_size_active.png'; 20 | import NormalSize from './normal_size.png'; 21 | import ScottLogicLogo from './scottlogic_logo.png'; 22 | import SearchTab from './search_tab.png'; 23 | import UndockActive from './undock_active.png'; 24 | import Undock from './undock.png'; 25 | 26 | export default { 27 | ArrowDown, 28 | ArrowUp, 29 | CloseActive, 30 | CloseIndicator, 31 | Close, 32 | CompactActive, 33 | Compact, 34 | StarHover, 35 | StarOffHover, 36 | StarOff, 37 | StarOn, 38 | FullViewActive, 39 | FullView, 40 | MaximizeActive, 41 | Maximize, 42 | MinimizeActive, 43 | Minimize, 44 | NoStarred, 45 | NormalSizeActive, 46 | NormalSize, 47 | ScottLogicLogo, 48 | SearchTab, 49 | UndockActive, 50 | Undock 51 | }; 52 | -------------------------------------------------------------------------------- /packages/stockflux-components/src/images/maximize.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/packages/stockflux-components/src/images/maximize.png -------------------------------------------------------------------------------- /packages/stockflux-components/src/images/maximize_active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/packages/stockflux-components/src/images/maximize_active.png -------------------------------------------------------------------------------- /packages/stockflux-components/src/images/minimize.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/packages/stockflux-components/src/images/minimize.png -------------------------------------------------------------------------------- /packages/stockflux-components/src/images/minimize_active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/packages/stockflux-components/src/images/minimize_active.png -------------------------------------------------------------------------------- /packages/stockflux-components/src/images/no_starred.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/packages/stockflux-components/src/images/no_starred.png -------------------------------------------------------------------------------- /packages/stockflux-components/src/images/normal_size.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/packages/stockflux-components/src/images/normal_size.png -------------------------------------------------------------------------------- /packages/stockflux-components/src/images/normal_size_active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/packages/stockflux-components/src/images/normal_size_active.png -------------------------------------------------------------------------------- /packages/stockflux-components/src/images/scottlogic_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/packages/stockflux-components/src/images/scottlogic_logo.png -------------------------------------------------------------------------------- /packages/stockflux-components/src/images/scroll_arrow_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/packages/stockflux-components/src/images/scroll_arrow_down.png -------------------------------------------------------------------------------- /packages/stockflux-components/src/images/scroll_arrow_up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/packages/stockflux-components/src/images/scroll_arrow_up.png -------------------------------------------------------------------------------- /packages/stockflux-components/src/images/search_tab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/packages/stockflux-components/src/images/search_tab.png -------------------------------------------------------------------------------- /packages/stockflux-components/src/images/star_hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/packages/stockflux-components/src/images/star_hover.png -------------------------------------------------------------------------------- /packages/stockflux-components/src/images/star_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/packages/stockflux-components/src/images/star_off.png -------------------------------------------------------------------------------- /packages/stockflux-components/src/images/star_off_hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/packages/stockflux-components/src/images/star_off_hover.png -------------------------------------------------------------------------------- /packages/stockflux-components/src/images/star_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/packages/stockflux-components/src/images/star_on.png -------------------------------------------------------------------------------- /packages/stockflux-components/src/images/star_tab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/packages/stockflux-components/src/images/star_tab.png -------------------------------------------------------------------------------- /packages/stockflux-components/src/images/undock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/packages/stockflux-components/src/images/undock.png -------------------------------------------------------------------------------- /packages/stockflux-components/src/images/undock_active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/packages/stockflux-components/src/images/undock_active.png -------------------------------------------------------------------------------- /packages/stockflux-components/src/styles/button-icon.css: -------------------------------------------------------------------------------- 1 | .button-icon { 2 | display: inline-block; 3 | width: var(--icons-size); 4 | height: 100%; 5 | background-position: 50% 80%; 6 | background-repeat: no-repeat; 7 | transition: 0.5s all; 8 | cursor: pointer; 9 | } 10 | 11 | .button-icon.minimize { 12 | background-image: url('../images/minimize.png'); 13 | } 14 | .button-icon.minimize:hover { 15 | background-image: url('../images/minimize_active.png'); 16 | } 17 | .button-icon.compact { 18 | background-image: url('../images/compact.png'); 19 | } 20 | .button-icon.compact:hover { 21 | background-image: url('../images/compact_active.png'); 22 | } 23 | .button-icon.full_view { 24 | background-image: url('../images/full_view.png'); 25 | } 26 | .button-icon.full_view:hover { 27 | background-image: url('../images/full_view_active.png'); 28 | } 29 | .button-icon.maximize { 30 | background-image: url('../images/maximize.png'); 31 | } 32 | .button-icon.maximize:hover { 33 | background-image: url('../images/maximize_active.png'); 34 | } 35 | .button-icon.normal_size { 36 | background-image: url('../images/normal_size.png'); 37 | } 38 | .button-icon.normal_size:hover { 39 | background-image: url('../images/normal_size_active.png'); 40 | } 41 | .button-icon.close { 42 | background-image: url('../images/close.png'); 43 | } 44 | .button-icon.close:hover { 45 | background-image: url('../images/close_active.png'); 46 | } 47 | .button-icon.undock { 48 | background-image: url('../images/undock.png'); 49 | } 50 | .button-icon.undock:hover { 51 | background-image: url('../images/undock_active.png'); 52 | } 53 | .button-icon.star { 54 | background-image: url('../images/star_off.png'); 55 | } 56 | .button-icon.star:hover { 57 | background-image: url('../images/star_off_hover.png'); 58 | } 59 | .button-icon.star.active { 60 | background-image: url('../images/star_on.png') !important; 61 | } 62 | .button-icon.star.active:hover { 63 | background-image: url('../images/star_hover.png') !important; 64 | } 65 | .button-icon.star.active:hover { 66 | background-image: url('../images/star_hover.png') !important; 67 | } 68 | .star-tab { 69 | background-image: url('../images/star_tab.png'); 70 | } -------------------------------------------------------------------------------- /packages/stockflux-components/src/styles/font.css: -------------------------------------------------------------------------------- 1 | @import url(https://fonts.googleapis.com/css?family=Roboto:400,100,300,500); 2 | 3 | body, input { 4 | font-family: "Roboto", sans-serif; 5 | font-size: var(--font-normal); 6 | font-weight: var(--font-weight-normal); 7 | -webkit-font-smoothing: antialiased; 8 | -moz-osx-font-smoothing: grayscale; 9 | } 10 | -------------------------------------------------------------------------------- /packages/stockflux-components/src/styles/icon.css: -------------------------------------------------------------------------------- 1 | .stockflux-icon { 2 | height: 19px; 3 | margin-top: auto; 4 | margin-bottom: auto; 5 | width: 30px; 6 | background-position: 50% 80%; 7 | background-repeat: no-repeat; 8 | transition: 0.5s all; 9 | cursor: default; 10 | display: inline-block; 11 | } 12 | 13 | .stockflux-icon.star-tab { 14 | background-image: url('../images/star_tab.png'); 15 | } 16 | 17 | .stockflux-icon.arrow-up { 18 | background-image: url('../images/arrow_up.png'); 19 | width: 20px; 20 | height: 10px; 21 | } 22 | 23 | .stockflux-icon.arrow-down { 24 | background-image: url('../images/arrow_down.png'); 25 | width: 20px; 26 | height: 10px; 27 | } -------------------------------------------------------------------------------- /packages/stockflux-components/src/styles/scrollbar.css: -------------------------------------------------------------------------------- 1 | ::-webkit-scrollbar { 2 | width: var(--scrollbar-width); 3 | background: transparent; 4 | } 5 | 6 | ::-webkit-scrollbar-track { 7 | border-radius: 0; 8 | background:transparent; 9 | } 10 | 11 | ::-webkit-scrollbar-thumb { 12 | border-radius: 3px; 13 | /* background-color: var(--scroll-bar-grip); */ 14 | background-color: rgba(98,116,130,0.8); 15 | } -------------------------------------------------------------------------------- /packages/stockflux-components/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = { 4 | mode: 'production', 5 | entry: path.resolve('src', 'index.js'), 6 | output: { 7 | filename: 'index.js', 8 | path: path.resolve(__dirname, 'dist'), 9 | library: 'stockflux-components', 10 | libraryTarget: 'umd' 11 | }, 12 | module: { 13 | rules: [ 14 | { 15 | test: /\.jsx?$/, 16 | include: [path.resolve(__dirname, 'src')], 17 | use: [{ loader: 'babel-loader' }] 18 | }, 19 | { 20 | test: /\.css$/, 21 | include: [path.resolve(__dirname, 'src')], 22 | use: [{ loader: 'style-loader' }, { loader: 'css-loader' }] 23 | }, 24 | { 25 | test: /\.png$/, 26 | include: [path.resolve(__dirname, 'src')], 27 | use: [{ loader: 'url-loader' }] 28 | }, 29 | { 30 | test: /\.svg$/, 31 | use: [ 32 | { 33 | loader: 'babel-loader' 34 | }, 35 | { 36 | loader: 'react-svg-loader', 37 | options: { 38 | jsx: true // true outputs JSX tags 39 | } 40 | } 41 | ] 42 | } 43 | ] 44 | }, 45 | externals: { 46 | react: 'react', 47 | 'openfin-react-hooks': 'openfin-react-hooks', 48 | 'openfin-layouts': 'openfin-layouts', 49 | 'date-fns': 'date-fns', 50 | 'openfin-fdc3': 'openfin-fdc3' 51 | } 52 | }; 53 | -------------------------------------------------------------------------------- /packages/stockflux-container/README.md: -------------------------------------------------------------------------------- 1 | ## Stockflux Container 2 | 3 | StockFlux Container is a part of StockFlux app suite intended to support the creation of multiple Chart and News apps. 4 | The container ran in headless mode so you will not see a window running for the application. It's primary purpose is to listen for Chart and News application intents and manage child windows based on the intent sent. 5 | 6 | ### Running locally 7 | 8 | In order to launch the StockFlux Container app locally, StockFlux Core and StockFlux Components have to be built first. 9 | Run the following commands in the root package to make lerna do the heavy lifting for you: 10 | 11 | ```bash 12 | npm install 13 | npm run bootstrap 14 | npm run build 15 | ``` 16 | 17 | 18 | To start and launch the StockFlux Container: 19 | 20 | ```bash 21 | npm start 22 | npm run launch 23 | ``` 24 | 25 | If you wish to see a window launched for the container for debugging purposes please change the `autoShow` and `frame` values in `app.dev.json` to `true`. 26 | 27 | To launch other StockFlux apps locally read the `README.md` files in the project folders. 28 | -------------------------------------------------------------------------------- /packages/stockflux-container/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "container", 3 | "version": "13.1.1", 4 | "private": true, 5 | "dependencies": { 6 | "date-fns": "^1.30.1", 7 | "openfin-fdc3": "^0.1.1", 8 | "openfin-layouts": "^1.0.3", 9 | "openfin-react-hooks": "^1.3.3", 10 | "react": "^16.8.6", 11 | "react-dom": "^16.8.6", 12 | "react-scripts": "3.0.1", 13 | "stockflux-core": "13.1.1" 14 | }, 15 | "homepage": "./", 16 | "scripts": { 17 | "start": "cross-env BROWSER=none PORT=8055 react-scripts start", 18 | "build": "react-scripts build", 19 | "test": "react-scripts test", 20 | "eject": "react-scripts eject" 21 | }, 22 | "browserslist": [ 23 | "chrome 68" 24 | ], 25 | "devDependencies": { 26 | "cross-env": "^5.2.0" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /packages/stockflux-container/public/app.dev.json: -------------------------------------------------------------------------------- 1 | { 2 | "runtime": { 3 | "arguments": "--enable-aggressive-domstorage-flushing", 4 | "version": "12.69.43.22" 5 | }, 6 | "startup_app": { 7 | "name": "stockflux-container", 8 | "uuid": "stockflux-container", 9 | "url": "http://localhost:8055/index.html", 10 | "applicationIcon": "{fqdn}/artifacts/stockflux-container/favicon.ico", 11 | "autoShow": true, 12 | "defaultWidth": 1280, 13 | "defaultHeight": 720, 14 | "minWidth": 1000, 15 | "minHeight": 600, 16 | "frame": false, 17 | "contextMenu": true, 18 | "customData": { 19 | "apiBaseUrl": "http://localhost:3010/api", 20 | "chartEntryPointUrl": "http://localhost:8051/index.html" 21 | } 22 | }, 23 | "services": [ 24 | { 25 | "name": "layouts", 26 | "config": { 27 | "features": { 28 | "tab": false 29 | } 30 | } 31 | } 32 | ], 33 | "shortcut": { 34 | "company": "ScottLogic", 35 | "description": "Hosts StockFlux Chart Container as an OpenFin application.", 36 | "name": "StockFlux Chart Container", 37 | "icon": "{fqdn}/artifacts/stockflux-container/v0.0.1/favicon.ico" 38 | }, 39 | "splashScreenImage": "{fqdn}/artifacts/stockflux-container/v0.0.1/splashscreen.png" 40 | } -------------------------------------------------------------------------------- /packages/stockflux-container/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/packages/stockflux-container/public/favicon.ico -------------------------------------------------------------------------------- /packages/stockflux-container/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 22 | React App 23 | 24 | 25 | 26 |
27 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /packages/stockflux-container/public/launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/packages/stockflux-container/public/launcher.png -------------------------------------------------------------------------------- /packages/stockflux-container/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": ".", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /packages/stockflux-container/public/splashscreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/packages/stockflux-container/public/splashscreen.png -------------------------------------------------------------------------------- /packages/stockflux-container/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | import * as serviceWorker from './serviceWorker'; 5 | 6 | ReactDOM.render(, document.getElementById('root')); 7 | 8 | // If you want your app to work offline and load faster, you can change 9 | // unregister() to register() below. Note this comes with some pitfalls. 10 | // Learn more about service workers: https://bit.ly/CRA-PWA 11 | serviceWorker.unregister(); 12 | -------------------------------------------------------------------------------- /packages/stockflux-core/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "stockflux-core", 3 | "version": "13.1.1", 4 | "private": true, 5 | "main": "dist/index.js", 6 | "peerDependencies": { 7 | "date-fns": "^1.30.1", 8 | "openfin-fdc3": "^0.1.1", 9 | "react": "^16.8.6", 10 | "throat": "^5.0.0" 11 | }, 12 | "scripts": { 13 | "build": "webpack" 14 | }, 15 | "browserslist": [ 16 | "chrome 68" 17 | ], 18 | "devDependencies": { 19 | "@babel/core": "^7.5.5", 20 | "@babel/preset-env": "^7.5.5", 21 | "babel-loader": "^8.0.6", 22 | "webpack": "^4.39.3", 23 | "webpack-cli": "^3.3.8" 24 | }, 25 | "dependencies": { 26 | "react-dom": "^16.10.2" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /packages/stockflux-core/src/custom-hooks/LocalStorageHook.js: -------------------------------------------------------------------------------- 1 | import { useState } from 'react'; 2 | 3 | export default function useLocalStorage(key, initialValue) { 4 | const [storedValue, setStoredValue] = useState(() => { 5 | try { 6 | const item = window.localStorage.getItem(key); 7 | return item ? JSON.parse(item) : initialValue; 8 | } catch (e) { 9 | return initialValue; 10 | } 11 | }); 12 | 13 | const setValue = value => { 14 | // Allow value to be a function so we have same API as useState 15 | const valueToStore = value instanceof Function ? value(storedValue) : value; 16 | setStoredValue(valueToStore); 17 | window.localStorage.setItem(key, JSON.stringify(valueToStore)); 18 | }; 19 | 20 | return [storedValue, setValue]; 21 | } 22 | -------------------------------------------------------------------------------- /packages/stockflux-core/src/index.js: -------------------------------------------------------------------------------- 1 | import useLocalStorage from './custom-hooks/LocalStorageHook'; 2 | import { addWatchlist, viewChart, viewNews, viewWatchlist } from './intents'; 3 | import { 4 | stockFluxSearch, 5 | getStockFluxData, 6 | getMiniChartData, 7 | getSymbolNews 8 | } from './services/StockFluxService'; 9 | import { truncate } from './utils/formatters'; 10 | import { 11 | createWindow, 12 | getCurrentWindow, 13 | getCurrentWindowSync, 14 | getChildWindows, 15 | getCurrentWindowOptions, 16 | getMonitorInfo, 17 | getAllApps, 18 | getStockFluxApps, 19 | getStockFluxApp, 20 | getWindow, 21 | openUrlWithBrowser, 22 | sendInterApplicationMessage, 23 | showNotification, 24 | useMain, 25 | windowAlreadyExists 26 | } from './openfin-api-utils/openfinApiHelpers'; 27 | import { launchChildWindow } from './services/ChildWindowLauncher'; 28 | import { 29 | launchChart, 30 | launchWatchlist, 31 | launchNews 32 | } from './services/app-launchers'; 33 | 34 | export const Utils = { 35 | truncate 36 | }; 37 | 38 | export const OpenfinApiHelpers = { 39 | createWindow, 40 | getCurrentWindow, 41 | getCurrentWindowSync, 42 | getChildWindows, 43 | getCurrentWindowOptions, 44 | getMonitorInfo, 45 | getAllApps, 46 | getStockFluxApps, 47 | getStockFluxApp, 48 | getWindow, 49 | openUrlWithBrowser, 50 | sendInterApplicationMessage, 51 | showNotification, 52 | useMain, 53 | windowAlreadyExists 54 | }; 55 | 56 | export const StockFlux = { 57 | stockFluxSearch, 58 | getStockFluxData, 59 | getMiniChartData, 60 | getSymbolNews 61 | }; 62 | 63 | export const Intents = { 64 | viewChart, 65 | viewNews, 66 | addWatchlist, 67 | viewWatchlist 68 | }; 69 | 70 | export const StockFluxHooks = { 71 | useLocalStorage 72 | }; 73 | 74 | export const Launchers = { 75 | launchChildWindow, 76 | launchChart, 77 | launchWatchlist, 78 | launchNews 79 | }; 80 | -------------------------------------------------------------------------------- /packages/stockflux-core/src/intents/addWatchlist.js: -------------------------------------------------------------------------------- 1 | import * as fdc3 from 'openfin-fdc3'; 2 | 3 | const defaultName = 'Apple Inc.'; 4 | const defaultSymbol = 'AAPL'; 5 | 6 | export default async (symbol, stockName) => 7 | fdc3.raiseIntent('WatchlistAdd', { 8 | type: 'security', 9 | name: stockName || defaultName, 10 | id: { 11 | default: symbol || defaultSymbol 12 | } 13 | }); 14 | -------------------------------------------------------------------------------- /packages/stockflux-core/src/intents/index.js: -------------------------------------------------------------------------------- 1 | import addWatchlist from './addWatchlist'; 2 | import viewWatchlist from './viewWatchlist'; 3 | import viewChart from './viewChart'; 4 | import viewNews from './viewNews'; 5 | 6 | export { addWatchlist, viewWatchlist, viewChart, viewNews }; 7 | -------------------------------------------------------------------------------- /packages/stockflux-core/src/intents/viewChart.js: -------------------------------------------------------------------------------- 1 | import * as fdc3 from 'openfin-fdc3'; 2 | 3 | const defaultName = 'Apple Inc.'; 4 | const defaultSymbol = 'AAPL'; 5 | 6 | export default async (symbol, stockName) => 7 | fdc3.raiseIntent(fdc3.Intents.VIEW_CHART, { 8 | type: 'security', 9 | name: symbol || defaultSymbol, 10 | appName: 'stockflux-chart', 11 | id: { 12 | default: stockName || defaultName 13 | } 14 | }); 15 | -------------------------------------------------------------------------------- /packages/stockflux-core/src/intents/viewNews.js: -------------------------------------------------------------------------------- 1 | import * as fdc3 from 'openfin-fdc3'; 2 | 3 | const defaultSymbol = 'AAPL'; 4 | const defaultCompany = 'Apple Inc.'; 5 | 6 | export default async (symbol, company) => 7 | fdc3.raiseIntent('ViewNews', { 8 | type: 'news', 9 | name: symbol || defaultSymbol, 10 | companyName: company || defaultCompany, 11 | appName: 'stockflux-news' 12 | }); 13 | -------------------------------------------------------------------------------- /packages/stockflux-core/src/intents/viewWatchlist.js: -------------------------------------------------------------------------------- 1 | import * as fdc3 from 'openfin-fdc3'; 2 | 3 | export default async () => 4 | fdc3.raiseIntent('WatchlistView', { type: 'security' }); 5 | -------------------------------------------------------------------------------- /packages/stockflux-core/src/services/ChildWindowLauncher.js: -------------------------------------------------------------------------------- 1 | import * as OpenfinApiHelpers from '../openfin-api-utils/openfinApiHelpers'; 2 | 3 | const createChildWindow = async options => { 4 | const childWindows = await OpenfinApiHelpers.getChildWindows(); 5 | const currentOptions = await OpenfinApiHelpers.getCurrentWindowOptions(); 6 | 7 | options.uuid = currentOptions.uuid; 8 | for (let i = 0; i < childWindows.length; i++) { 9 | const childWindowOptions = await childWindows[i].getOptions(); 10 | if (childWindowOptions.name === options.name) { 11 | if (childWindows[i]) { 12 | childWindows[i].bringToFront(); 13 | return true; 14 | } 15 | break; 16 | } 17 | } 18 | 19 | await OpenfinApiHelpers.createWindow(options); 20 | return true; 21 | }; 22 | 23 | const getChildWindowOptions = async manifest => { 24 | const manifestUrl = 25 | typeof manifest === 'string' ? manifest : manifest.manifest; 26 | 27 | const response = await fetch(manifestUrl); 28 | if (!response.ok) { 29 | throw new Error('Could not retrieve manifest'); 30 | } 31 | 32 | const body = await response.json(); 33 | return body.startup_app; 34 | }; 35 | 36 | export const launchChildWindow = async (manifest, modifyOptions) => { 37 | modifyOptions = modifyOptions === undefined ? o => o : modifyOptions; 38 | 39 | return await createChildWindow( 40 | modifyOptions(await getChildWindowOptions(manifest)) 41 | ); 42 | }; 43 | -------------------------------------------------------------------------------- /packages/stockflux-core/src/services/app-launchers/Chart.js: -------------------------------------------------------------------------------- 1 | import { getStockFluxApp } from '../../openfin-api-utils/openfinApiHelpers'; 2 | import { launchChildWindow } from '../ChildWindowLauncher'; 3 | import viewChart from '../../intents/viewChart'; 4 | 5 | const APP_NAME = 'stockflux-chart'; 6 | 7 | const launchAsIntent = (symbol, name) => 8 | symbol && name ? viewChart(symbol, name) : viewChart(); 9 | 10 | const launchAsChildWindow = async (symbol, name, position) => 11 | launchChildWindow(await getStockFluxApp(APP_NAME), options => { 12 | options.name = `${APP_NAME}${symbol ? `[${symbol}]` : ''}`; 13 | if (symbol) { 14 | options.customData.symbol = symbol; 15 | } 16 | if (name) { 17 | options.customData.name = name; 18 | } 19 | if (position) { 20 | options.defaultLeft = position.left; 21 | options.defaultTop = position.top; 22 | } 23 | return options; 24 | }); 25 | 26 | export default (symbol, name, position, intentsEnabled) => 27 | intentsEnabled 28 | ? launchAsIntent(symbol, name) 29 | : launchAsChildWindow(symbol, name, position); 30 | -------------------------------------------------------------------------------- /packages/stockflux-core/src/services/app-launchers/News.js: -------------------------------------------------------------------------------- 1 | import { getStockFluxApp } from '../../openfin-api-utils/openfinApiHelpers'; 2 | import { launchChildWindow } from '../ChildWindowLauncher'; 3 | import viewNews from '../../intents/viewNews'; 4 | 5 | const APP_NAME = 'stockflux-news'; 6 | 7 | const launchAsIntent = (symbol, name) => 8 | symbol && name ? viewNews(symbol, name) : viewNews(); 9 | 10 | const launchAsChildWindow = async (symbol, name) => 11 | launchChildWindow(await getStockFluxApp(APP_NAME), options => { 12 | options.name = `${APP_NAME}${symbol ? `[${symbol}]` : ''}`; 13 | if (symbol) { 14 | options.customData.symbol = symbol; 15 | } 16 | if (name) { 17 | options.customData.name = name; 18 | } 19 | return options; 20 | }); 21 | 22 | export default (symbol, name, intentsEnabled) => 23 | intentsEnabled 24 | ? launchAsIntent(symbol, name) 25 | : launchAsChildWindow(symbol, name); 26 | -------------------------------------------------------------------------------- /packages/stockflux-core/src/services/app-launchers/Watchlist.js: -------------------------------------------------------------------------------- 1 | import { 2 | getStockFluxApp, 3 | getCurrentWindowOptions, 4 | sendInterApplicationMessage 5 | } from '../../openfin-api-utils/openfinApiHelpers'; 6 | import { launchChildWindow } from '../ChildWindowLauncher'; 7 | import viewWatchlist from '../../intents/viewWatchlist'; 8 | import addToWatchlist from '../../intents/addWatchlist'; 9 | 10 | const APP_NAME = 'stockflux-watchlist'; 11 | 12 | const launchAsIntent = (symbol, name) => 13 | symbol && name ? addToWatchlist(symbol, name) : viewWatchlist(); 14 | 15 | const launchAsChildWindow = async (symbol, name) => { 16 | const childWindow = await launchChildWindow( 17 | await getStockFluxApp(APP_NAME), 18 | options => { 19 | options.name = APP_NAME; 20 | options.customData.symbol = symbol; 21 | options.customData.name = name; 22 | return options; 23 | } 24 | ); 25 | try { 26 | const options = await getCurrentWindowOptions(); 27 | await sendInterApplicationMessage(options ? options.uuid : '*', APP_NAME, { 28 | symbol, 29 | name 30 | }); 31 | } catch (err) { 32 | console.error(err); 33 | } 34 | 35 | return childWindow; 36 | }; 37 | 38 | export default (symbol, name, intentsEnabled) => 39 | intentsEnabled 40 | ? launchAsIntent(symbol, name) 41 | : launchAsChildWindow(symbol, name); 42 | -------------------------------------------------------------------------------- /packages/stockflux-core/src/services/app-launchers/index.js: -------------------------------------------------------------------------------- 1 | import launchChart from './Chart'; 2 | import launchWatchlist from './Watchlist'; 3 | import launchNews from './News'; 4 | 5 | export { launchChart, launchWatchlist, launchNews }; 6 | -------------------------------------------------------------------------------- /packages/stockflux-core/src/utils/formatters.js: -------------------------------------------------------------------------------- 1 | export const truncate = input => { 2 | const openBracketIndex = input.indexOf('('); 3 | return openBracketIndex === -1 ? input : input.slice(0, openBracketIndex - 1); 4 | }; 5 | -------------------------------------------------------------------------------- /packages/stockflux-core/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = { 4 | mode: 'production', 5 | entry: path.resolve('src', 'index.js'), 6 | output: { 7 | filename: 'index.js', 8 | path: path.resolve(__dirname, 'dist'), 9 | library: 'stockflux-core', 10 | libraryTarget: 'umd' 11 | }, 12 | module: { 13 | rules: [ 14 | { 15 | test: /\.js$/, 16 | include: [path.resolve(__dirname, 'src')], 17 | use: [{ loader: 'babel-loader' }] 18 | } 19 | ] 20 | }, 21 | externals: { 22 | 'date-fns': 'date-fns', 23 | react: 'react', 24 | throat: 'throat', 25 | 'openfin-fdc3': 'openfin-fdc3' 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /packages/stockflux-launcher/README.md: -------------------------------------------------------------------------------- 1 | ## StockFlux Launcher 2 | 3 | StockFlux Launcher is a part of StockFlux app suite intended to work with StockFlux Watchlist, Chart, and News apps. The launcher is considered to be the centre of the StockFlux application suite. It is used to launch the other applications either directly via icons or by searching for a symbol and opening using the results returned. 4 | 5 | ### Launching StockFlux Launcher app from the installer 6 | 7 | Download the [installer](https://install.openfin.co/download/?os=win&config=https%3A%2F%2Fstockflux.scottlogic.com%2Fapi%2Fapps%2Fv1%2Fstockflux-launcher%2Fapp.json&fileName=stockflux&unzipped=true). After installing `StockFlux Launcher` icon should appear on the desktop. Double click it to open the StockFlux Launcher. 8 | 9 | ### Running locally 10 | 11 | In order to launch the StockFlux Launcher app locally, StockFlux Core and StockFlux Components have to be built first. 12 | Run the following commands in the root package to make lerna do the heavy lifting for you: 13 | 14 | ```bash 15 | npm install 16 | npm run bootstrap 17 | npm run build 18 | ``` 19 | 20 | 21 | To start and launch the StockFlux Launcher: 22 | 23 | ```bash 24 | npm start 25 | npm run launch 26 | ``` 27 | 28 | To launch other StockFlux apps locally read the `README.md` files in the project folders. 29 | 30 | ### Launcher functionality 31 | 32 | - The launcher's main feature is the search bar in the middle of the application. The user can search for a symbol and then launch one of our 3 applications, Chart, News or Watchlist. 33 | - The 3 apps can be launched on their own without searching for a symbol. Each icon in the left side of the Application relates to each app. When this is done the for the News and Chart application the symbol "AAPL" is used as a default. 34 | - Once an application has been launched the launcher can be closed. It will not effect the application you have just opened. 35 | - The launcher can be docked to the top, left and right of the screen. It can also be dragged to any other position on the screen. 36 | -------------------------------------------------------------------------------- /packages/stockflux-launcher/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "stockflux-launcher", 3 | "version": "13.1.1", 4 | "private": true, 5 | "dependencies": { 6 | "classnames": "^2.2.6", 7 | "date-fns": "1.30.1", 8 | "openfin-fdc3": "^0.1.1", 9 | "openfin-layouts": "^1.0.0", 10 | "openfin-react-hooks": "^1.3.3", 11 | "prop-types": "15.7.2", 12 | "react": "^16.8.6", 13 | "react-dom": "^16.8.6", 14 | "react-icons": "^3.7.0", 15 | "react-scripts": "3.0.1", 16 | "stockflux-components": "13.1.1", 17 | "stockflux-core": "13.1.1", 18 | "throat": "4.1.0" 19 | }, 20 | "homepage": "./", 21 | "scripts": { 22 | "start": "cross-env BROWSER=none PORT=8053 react-scripts start", 23 | "launch": "openfin --launch --config ./public/app.dev.json", 24 | "launch-appd": "openfin --launch --config http://localhost:3000/api/apps/v1/stockflux-launcher/app.json", 25 | "build": "react-scripts build", 26 | "test": "react-scripts test", 27 | "eject": "react-scripts eject" 28 | }, 29 | "browserslist": [ 30 | "chrome 68" 31 | ], 32 | "devDependencies": { 33 | "cross-env": "^5.2.0", 34 | "openfin-cli": "^2.0.8" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/stockflux-launcher/public/child-window.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | -------------------------------------------------------------------------------- /packages/stockflux-launcher/public/childWindow.css: -------------------------------------------------------------------------------- 1 | body { 2 | overflow-x: hidden; 3 | height: inherit; 4 | background-color: #071521; 5 | } 6 | 7 | div#root { 8 | height:100vh; 9 | flex: 1 1 auto; 10 | overflow:hidden; 11 | } 12 | 13 | div.scrollWrapperY > p { 14 | text-align: center; 15 | color: var(--text-grey-light); 16 | padding: 170px 50px; 17 | font-weight: var(--font-weight-bold); 18 | letter-spacing: 0.2px; 19 | margin: 0; 20 | } 21 | 22 | .spinner { 23 | position: relative; 24 | top:calc(50vh - var(--search-input-height)) 25 | } 26 | 27 | .card { 28 | padding: 1px; 29 | padding-left:18px; 30 | background-color: #0D2437; 31 | height:40px; 32 | display: flex; 33 | align-items: center; 34 | justify-content: space-between; 35 | border-bottom: 1px solid var(--clr-divider-light); 36 | } 37 | 38 | .card p { 39 | cursor: default; 40 | margin: var(--margin-medium); 41 | } 42 | 43 | div#actions { 44 | float: right; 45 | margin: 0 var(--margin-small); 46 | display: none; 47 | /*min-width:422px;*/ 48 | flex-shrink: 0; 49 | } 50 | 51 | .card:hover { 52 | background-color: #1B3B56; 53 | } 54 | 55 | .card:hover > .actions { 56 | display:flex !important; 57 | } 58 | 59 | .name { 60 | letter-spacing: 0.5px; 61 | line-height: 16px; 62 | font-size: 14px; 63 | font-weight: var(--font-weight-bold); 64 | color: var(--text-color); 65 | text-overflow: ellipsis; 66 | white-space: nowrap; 67 | } 68 | 69 | .info { 70 | flex-shrink: 1; 71 | flex-grow: 1; 72 | overflow-x: hidden; 73 | } 74 | 75 | .actions { 76 | flex-shrink: 0; 77 | flex-grow: 0; 78 | } -------------------------------------------------------------------------------- /packages/stockflux-launcher/public/dockSelector.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color:#1b3b56; 3 | } 4 | 5 | div#root { 6 | overflow:hidden; 7 | } -------------------------------------------------------------------------------- /packages/stockflux-launcher/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/packages/stockflux-launcher/public/favicon.ico -------------------------------------------------------------------------------- /packages/stockflux-launcher/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | StockFlux 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | -------------------------------------------------------------------------------- /packages/stockflux-launcher/public/launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/packages/stockflux-launcher/public/launcher.png -------------------------------------------------------------------------------- /packages/stockflux-launcher/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "StockFlux App Launcher", 3 | "name": "StockFlux App Launcher", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": ".", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } -------------------------------------------------------------------------------- /packages/stockflux-launcher/public/popupWindow.css: -------------------------------------------------------------------------------- 1 | html { 2 | border-radius: 5px; 3 | 4 | } 5 | body { 6 | overflow: hidden; 7 | padding: 4vh 4vw; 8 | border: none; 9 | box-sizing: border-box; 10 | background-color: var(--window-background-color); 11 | box-shadow: 0px 2px 9 3 rgba(91,91,91,0.5); 12 | } 13 | 14 | .popup { 15 | color: var(--text-color); 16 | width: 100%; 17 | } 18 | 19 | .popup-message { 20 | text-align: center; 21 | font-size: var(--font-large); 22 | line-height: 21px; 23 | margin-top: 28px; 24 | height: 42px; 25 | margin-left: 50px; 26 | margin-right: 50px; 27 | } 28 | 29 | .popup-options { 30 | text-align: right; 31 | display: flex; 32 | flex-direction: row; 33 | margin-left: 34px; 34 | margin-right: 34px; 35 | justify-content: space-between; 36 | } 37 | 38 | .popup-options button { 39 | flex-grow: 1; 40 | border: none; 41 | background-color: var(--color-highlight); 42 | border-radius: 3px; 43 | max-width: 80px; 44 | height:27px; 45 | } 46 | -------------------------------------------------------------------------------- /packages/stockflux-launcher/public/splashscreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/packages/stockflux-launcher/public/splashscreen.png -------------------------------------------------------------------------------- /packages/stockflux-launcher/src/app-shortcuts/AppShortcuts.css: -------------------------------------------------------------------------------- 1 | .app-shortcuts { 2 | display: flex; 3 | align-items: center; 4 | } 5 | 6 | .left .app-shortcuts, 7 | .right .app-shortcuts { 8 | flex-direction: column; 9 | } 10 | -------------------------------------------------------------------------------- /packages/stockflux-launcher/src/app-shortcuts/AppShortcuts.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from 'react'; 2 | import { OpenfinApiHelpers } from 'stockflux-core'; 3 | import Components from 'stockflux-components'; 4 | import './AppShortcuts.css'; 5 | 6 | export default ({ showTitle }) => { 7 | const [apps, setApps] = useState([]); 8 | 9 | useEffect(() => { 10 | OpenfinApiHelpers.getAllApps() 11 | .then(setApps) 12 | .catch(console.error); 13 | }, []); 14 | 15 | return ( 16 |
17 | {apps 18 | .filter( 19 | app => 20 | app.customConfig !== undefined && 21 | app.customConfig.showInLauncher && 22 | app.appId.indexOf('stockflux-') === 0 23 | ) 24 | .map(app => { 25 | const AppShortcut = 26 | Components.Shortcuts[ 27 | app.appId 28 | .split('stockflux-')[1] 29 | .charAt(0) 30 | .toUpperCase() + app.appId.slice(11) 31 | ]; 32 | return ( 33 | 40 | ); 41 | })} 42 | {apps 43 | .filter( 44 | app => 45 | app.customConfig !== undefined && 46 | app.customConfig.showInLauncher && 47 | app.appId.indexOf('stockflux-') === -1 48 | ) 49 | .map(app => { 50 | return ( 51 | 57 | ); 58 | })} 59 |
60 | ); 61 | }; 62 | -------------------------------------------------------------------------------- /packages/stockflux-launcher/src/dock-selector/DockSelector.css: -------------------------------------------------------------------------------- 1 | .horizontal.dockselector button { 2 | width:96px; 3 | } -------------------------------------------------------------------------------- /packages/stockflux-launcher/src/dock-selector/GetSelectionWindowProps.js: -------------------------------------------------------------------------------- 1 | import getPosition from './Positioner'; 2 | 3 | export default (name, bounds, dockedTo, dockSelectorButton, size) => { 4 | const { defaultHeight, defaultWidth } = 5 | dockedTo === 'right' || dockedTo === 'left' 6 | ? { defaultHeight: size.defaultHeight, defaultWidth: 0 } 7 | : { defaultHeight: 0, defaultWidth: size.defaultWidth }; 8 | const { defaultTop, defaultLeft } = getPosition( 9 | dockSelectorButton, 10 | dockedTo, 11 | bounds, 12 | defaultHeight, 13 | defaultWidth 14 | ); 15 | 16 | return { 17 | name: name, 18 | url: 'child-window.html', 19 | frame: false, 20 | autoShow: true, 21 | defaultTop, 22 | defaultLeft, 23 | defaultWidth, 24 | defaultHeight, 25 | saveWindowState: false, 26 | showTaskbarIcon: false, 27 | backgroundColor: '#071521', 28 | waitForPageLoad: true, 29 | alwaysOnTop: true, 30 | resizable: false, 31 | cornerRounding: { 32 | width: 3, 33 | height: 3 34 | } 35 | }; 36 | }; 37 | -------------------------------------------------------------------------------- /packages/stockflux-launcher/src/dock-selector/Positioner.js: -------------------------------------------------------------------------------- 1 | import { ScreenEdge } from 'openfin-react-hooks'; 2 | 3 | const DEFAULT_OFFSET_SIZE = 0; 4 | 5 | export default (searchButtonRef, dockedTo, windowBounds, height, width) => { 6 | const searchButtonRect = searchButtonRef.current.getBoundingClientRect(); 7 | switch (dockedTo) { 8 | case ScreenEdge.TOP: 9 | return { 10 | defaultTop: parseInt(windowBounds.bottom), 11 | defaultLeft: windowBounds.left + parseInt(searchButtonRect.left) 12 | }; 13 | case ScreenEdge.LEFT: 14 | return { 15 | defaultTop: parseInt(searchButtonRect.top), 16 | defaultLeft: windowBounds.right 17 | }; 18 | case ScreenEdge.RIGHT: 19 | return { 20 | defaultTop: parseInt(searchButtonRect.top), 21 | defaultLeft: windowBounds.left - width + DEFAULT_OFFSET_SIZE 22 | }; 23 | default: 24 | return { 25 | defaultTop: windowBounds.top + parseInt(searchButtonRect.bottom), 26 | defaultLeft: windowBounds.left + parseInt(searchButtonRect.left) 27 | }; 28 | } 29 | }; 30 | -------------------------------------------------------------------------------- /packages/stockflux-launcher/src/free-text-search/FreeTextSearch.css: -------------------------------------------------------------------------------- 1 | .free-text-search { 2 | flex: 0 1; 3 | display: flex; 4 | justify-content: center; 5 | align-items: center; 6 | font-family: var(--font-family); 7 | width:710px; 8 | min-width:710px; 9 | background-color: #071521; 10 | border-radius: 5px; 11 | padding-top:5px; 12 | padding-bottom:5px; 13 | } 14 | 15 | .free-text-search input { 16 | background: #071521; 17 | flex-grow:1; 18 | color: var(--text-color); 19 | border: none; 20 | border-radius: 4px; 21 | font-size: 16px; 22 | height: var(--search-input-height); 23 | width: var(--search-input-width); 24 | margin: 0 12px; 25 | outline: none; 26 | } 27 | 28 | .search-undocked { 29 | width: 350px; 30 | min-width: 0px; 31 | flex-grow: 1; 32 | } 33 | 34 | .left .free-text-search, 35 | .right .free-text-search { 36 | flex-direction: column; 37 | min-width: 0; 38 | width: 100%; 39 | flex: inherit; 40 | background-color: var(--window-background-color); 41 | } 42 | 43 | .left .free-text-search input, 44 | .right .free-text-search input { 45 | display: none; 46 | } 47 | 48 | .searchSVG { 49 | color: var(--icon-inactive); 50 | width: 40px; 51 | } 52 | 53 | .searchSVG:hover{ 54 | color: var(--icon-active); 55 | } 56 | 57 | div#root > .free-text-search { 58 | padding: 8px 10px 8px 0; 59 | width: var(--search-input-width); 60 | border-bottom: 1px solid var(--clr-divider-light); 61 | } 62 | 63 | div#root > .spinner { 64 | margin: calc(var(--search-input-width) / 2 - 15px); 65 | position: fixed; 66 | } 67 | 68 | div#root > .cards.padding-top { 69 | padding-top: calc(var(--search-input-height) + 18px); 70 | } 71 | 72 | .actions-button { 73 | display: inline-block; 74 | color: var(--text-color); 75 | fill: var(--text-color); 76 | border: none; 77 | outline: none; 78 | background-color: inherit; 79 | cursor: pointer; 80 | display: flex; 81 | align-items: center; 82 | border-radius: 4px; 83 | height: 40px; 84 | padding-left: 15px; 85 | padding-right: 15px; 86 | border: 1.5px transparent; 87 | } 88 | 89 | .actions-button:hover { 90 | background-color: #475F74; 91 | border: 1.5px solid #FFFFFF; 92 | } 93 | -------------------------------------------------------------------------------- /packages/stockflux-launcher/src/free-text-search/SearchButton.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Components from 'stockflux-components'; 3 | 4 | export default ({ searchButtonRef, handleSearchClick }) => ( 5 | 6 | 7 | 8 | 9 | 10 | ); 11 | -------------------------------------------------------------------------------- /packages/stockflux-launcher/src/free-text-search/SearchInputField.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default ({ query, inputRef, handleOnInputChange }) => ( 4 | 10 | ); 11 | -------------------------------------------------------------------------------- /packages/stockflux-launcher/src/index.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --margin-large: 15px; 3 | --search-input-min-width: 250px; 4 | --search-input-width: 396px; 5 | --search-input-width-undocked: 360px; 6 | --search-input-height: 30px; 7 | } 8 | 9 | * { 10 | box-sizing: border-box; 11 | } 12 | 13 | body { 14 | padding: 0; 15 | margin: 0; 16 | width: 100vw; 17 | height: 100vh; 18 | } 19 | 20 | #root { 21 | width: 100%; 22 | height: 100%; 23 | } 24 | -------------------------------------------------------------------------------- /packages/stockflux-launcher/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import { OpenfinApiHelpers } from 'stockflux-core'; 4 | import App from './App'; 5 | 6 | import './index.css'; 7 | 8 | const mountApp = () => { 9 | ReactDOM.render(, document.getElementById('root')); 10 | }; 11 | 12 | if (OpenfinApiHelpers.getWindow()) { 13 | OpenfinApiHelpers.useMain(mountApp); 14 | } else { 15 | console.error('This application can only be run in an OpenFin container.'); 16 | } 17 | -------------------------------------------------------------------------------- /packages/stockflux-launcher/src/reducers/child-window/Action.js: -------------------------------------------------------------------------------- 1 | export default { 2 | CHANGE_STATE: 'CHANGE_STATE', 3 | SET_WINDOW: 'SET_WINDOW', 4 | LAUNCH: 'LAUNCH', 5 | POPULATE: 'POPULATE', 6 | CLOSE: 'CLOSE', 7 | RESET: 'RESET' 8 | }; 9 | -------------------------------------------------------------------------------- /packages/stockflux-launcher/src/reducers/child-window/ChildWindow.js: -------------------------------------------------------------------------------- 1 | import stateType from './State'; 2 | import actionType from './Action'; 3 | 4 | export const initialChildWindowState = { 5 | window: null, 6 | state: stateType.INITIAL 7 | }; 8 | 9 | export default (state, action) => { 10 | switch (action.type) { 11 | case actionType.CHANGE_STATE: 12 | if (!Object.keys(stateType).includes(action.payload)) 13 | throw new Error(`Invalid window state: ${action.payload}.`); 14 | else if (action.payload === stateType.ERROR) 15 | throw new Error( 16 | `Error occured while window was in this state: ${action.payload}.` 17 | ); 18 | return { ...state, state: action.payload }; 19 | case actionType.SET_WINDOW: 20 | return { ...state, window: action.payload }; 21 | case actionType.RESET: 22 | return initialChildWindowState; 23 | default: 24 | throw new Error(`Invalid action type: ${action.type}.`); 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /packages/stockflux-launcher/src/reducers/child-window/State.js: -------------------------------------------------------------------------------- 1 | export default { 2 | INITIAL: 'INITIAL', 3 | LAUNCHING: 'LAUNCHING', 4 | LAUNCHED: 'LAUNCHED', 5 | POPULATING: 'POPULATING', 6 | POPULATED: 'POPULATED', 7 | ERROR: 'ERROR' 8 | }; 9 | -------------------------------------------------------------------------------- /packages/stockflux-launcher/src/reducers/free-text-search/Action.js: -------------------------------------------------------------------------------- 1 | export default { 2 | SEARCHING: 'SEARCHING', 3 | SUCCESS: 'SUCCESS', 4 | ERROR: 'ERROR', 5 | INITIALISE: 'INITIALISE' 6 | }; 7 | -------------------------------------------------------------------------------- /packages/stockflux-launcher/src/reducers/free-text-search/FreeTextSearch.js: -------------------------------------------------------------------------------- 1 | import actionType from './Action'; 2 | 3 | export const initialSearchState = { 4 | isSearching: false, 5 | hasErrors: false, 6 | results: [] 7 | }; 8 | 9 | export default (state, { type, results }) => { 10 | switch (type) { 11 | case actionType.SEARCHING: 12 | return { 13 | ...state, 14 | hasErrors: false, 15 | isSearching: true, 16 | results: [] 17 | }; 18 | case actionType.SUCCESS: 19 | return { 20 | ...state, 21 | isSearching: false, 22 | results 23 | }; 24 | case actionType.ERROR: 25 | return { 26 | ...state, 27 | hasErrors: true, 28 | isSearching: false, 29 | results: [] 30 | }; 31 | case actionType.INITIALISE: 32 | return initialSearchState; 33 | default: 34 | throw new Error(); 35 | } 36 | }; 37 | -------------------------------------------------------------------------------- /packages/stockflux-launcher/src/reducers/search-result/Action.js: -------------------------------------------------------------------------------- 1 | export default { 2 | SEARCHING: 'SEARCHING', 3 | SUCCESS: 'SUCCESS', 4 | ERROR: 'ERROR', 5 | INITIALISE: 'INITIALISE' 6 | }; 7 | -------------------------------------------------------------------------------- /packages/stockflux-launcher/src/reducers/search-result/SearchResult.js: -------------------------------------------------------------------------------- 1 | import ActionType from './Action'; 2 | 3 | export const initialSearchState = { 4 | isSearching: false, 5 | hasErrors: false 6 | }; 7 | 8 | export default (state, { type, results }) => { 9 | switch (type) { 10 | case ActionType.SEARCHING: 11 | return { 12 | ...state, 13 | hasErrors: false, 14 | isSearching: true 15 | }; 16 | case ActionType.SUCCESS: 17 | return { 18 | ...state, 19 | isSearching: false, 20 | results 21 | }; 22 | case ActionType.ERROR: 23 | return { 24 | ...state, 25 | hasErrors: true, 26 | isSearching: false 27 | }; 28 | case ActionType.INITIALISE: 29 | return initialSearchState; 30 | default: 31 | throw new Error(); 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /packages/stockflux-launcher/src/search-results/ChildWindow.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Components from 'stockflux-components'; 3 | import messages from './messages'; 4 | import SearchResults from './SearchResults'; 5 | 6 | export default ({ results, children, isSearching, debouncedQuery }) => { 7 | const messageJsx = isSearching ? ( 8 | 9 | ) : ( 10 |

{debouncedQuery ? messages.NO_MATCHES : messages.INITIAL}

11 | ); 12 | 13 | return ( 14 | <> 15 | {children} 16 | 17 | {results && results.length > 0 ? ( 18 | 19 | ) : ( 20 | messageJsx 21 | )} 22 | 23 | 24 | ); 25 | }; 26 | -------------------------------------------------------------------------------- /packages/stockflux-launcher/src/search-results/Launcher.js: -------------------------------------------------------------------------------- 1 | import getWindowPosition from './helpers/Positioner'; 2 | import { OpenfinApiHelpers } from 'stockflux-core'; 3 | 4 | export default async ( 5 | searchButtonRef, 6 | searchInputRef, 7 | dockedTo, 8 | windowBounds 9 | ) => { 10 | const { 11 | defaultTop, 12 | defaultLeft, 13 | defaultWidth, 14 | defaultHeight 15 | } = getWindowPosition( 16 | searchButtonRef, 17 | searchInputRef, 18 | dockedTo, 19 | windowBounds 20 | ); 21 | 22 | const childWindow = { 23 | name: 'search-results', 24 | defaultWidth, 25 | defaultHeight, 26 | url: 'child-window.html', 27 | frame: false, 28 | autoShow: true, 29 | defaultTop, 30 | defaultLeft, 31 | saveWindowState: false, 32 | showTaskbarIcon: false, 33 | backgroundColor: '#28313D', 34 | waitForPageLoad: true, 35 | alwaysOnTop: false, 36 | maxWidth: 400, 37 | minWidth: 400, 38 | minHeight: 300 39 | }; 40 | 41 | return await OpenfinApiHelpers.createWindow(childWindow); 42 | }; 43 | -------------------------------------------------------------------------------- /packages/stockflux-launcher/src/search-results/SearchResult.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Components from 'stockflux-components'; 3 | import * as PropTypes from 'prop-types'; 4 | import { Utils, Launchers } from 'stockflux-core'; 5 | 6 | const SearchResult = ({ symbol, name }) => { 7 | return ( 8 |
9 |
10 |

11 | {symbol.toUpperCase()} * {Utils.truncate(name)} 12 |

13 |
14 |
15 | 21 | 27 | 33 |
34 |
35 | ); 36 | }; 37 | 38 | SearchResult.propTypes = { 39 | symbol: PropTypes.string.isRequired, 40 | name: PropTypes.string.isRequired 41 | }; 42 | 43 | export default SearchResult; 44 | -------------------------------------------------------------------------------- /packages/stockflux-launcher/src/search-results/SearchResults.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import classNames from 'classnames'; 3 | import SearchResult from './SearchResult'; 4 | 5 | export default ({ results, paddingNeeded }) => 6 | results && 7 | results.length > 0 && ( 8 |
9 | {results.map(result => ( 10 | 15 | ))} 16 |
17 | ); 18 | -------------------------------------------------------------------------------- /packages/stockflux-launcher/src/search-results/helpers/GetResultsWindowProps.js: -------------------------------------------------------------------------------- 1 | import getWindowPosition from './Positioner'; 2 | 3 | export default ( 4 | name, 5 | searchButtonRef, 6 | searchInputRef, 7 | dockedTo, 8 | windowBounds 9 | ) => { 10 | const { 11 | defaultTop, 12 | defaultLeft, 13 | defaultWidth, 14 | defaultHeight 15 | } = getWindowPosition( 16 | searchButtonRef, 17 | searchInputRef, 18 | dockedTo, 19 | windowBounds 20 | ); 21 | return { 22 | name: name, 23 | defaultWidth, 24 | defaultHeight, 25 | url: 'child-window.html', 26 | frame: false, 27 | autoShow: true, 28 | defaultTop, 29 | defaultLeft, 30 | saveWindowState: false, 31 | showTaskbarIcon: false, 32 | backgroundColor: '#071521', 33 | waitForPageLoad: true, 34 | alwaysOnTop: false, 35 | maxWidth: 710, 36 | minWidth: 710, 37 | minHeight: 350, 38 | resizable: false 39 | }; 40 | }; 41 | -------------------------------------------------------------------------------- /packages/stockflux-launcher/src/search-results/helpers/Launcher.js: -------------------------------------------------------------------------------- 1 | import getWindowPosition from './Positioner'; 2 | import { OpenfinApiHelpers } from 'stockflux-core'; 3 | 4 | export default async ( 5 | searchButtonRef, 6 | searchInputRef, 7 | dockedTo, 8 | windowBounds 9 | ) => { 10 | const { 11 | defaultTop, 12 | defaultLeft, 13 | defaultWidth, 14 | defaultHeight 15 | } = getWindowPosition( 16 | searchButtonRef, 17 | searchInputRef, 18 | dockedTo, 19 | windowBounds 20 | ); 21 | 22 | const childWindow = { 23 | name: 'search-results', 24 | defaultWidth, 25 | defaultHeight, 26 | url: 'child-window.html', 27 | frame: false, 28 | autoShow: true, 29 | defaultTop, 30 | defaultLeft, 31 | saveWindowState: false, 32 | showTaskbarIcon: false, 33 | backgroundColor: '#28313D', 34 | waitForPageLoad: true, 35 | alwaysOnTop: false, 36 | maxWidth: 400, 37 | minWidth: 400, 38 | minHeight: 300 39 | }; 40 | 41 | const win = await OpenfinApiHelpers.createWindow(childWindow); 42 | 43 | return win; 44 | }; 45 | -------------------------------------------------------------------------------- /packages/stockflux-launcher/src/search-results/helpers/Populater.js: -------------------------------------------------------------------------------- 1 | import ReactDOM from 'react-dom'; 2 | 3 | export default (html, childWindow, css) => { 4 | const childDocument = childWindow.getWebWindow().document; 5 | 6 | ReactDOM.render(html, childDocument.getElementById('root')); 7 | 8 | const parentStyles = document.getElementsByTagName('style'); 9 | const parentScripts = document.getElementsByTagName('script'); 10 | 11 | injectNodesToChildHead(childDocument, parentStyles); 12 | injectNodesToChildHead(childDocument, parentScripts); 13 | 14 | if (css) { 15 | var linkElement = document.createElement('link'); 16 | linkElement.setAttribute('rel', 'stylesheet'); 17 | linkElement.setAttribute('href', css); 18 | injectNodeToChildHead(childDocument, linkElement); 19 | } 20 | }; 21 | 22 | const injectNodesToChildHead = (childDocument, nodes) => { 23 | for (let node of nodes) { 24 | injectNodeToChildHead(childDocument, node); 25 | } 26 | }; 27 | 28 | const injectNodeToChildHead = (childDocument, node) => { 29 | childDocument 30 | .getElementsByTagName('head')[0] 31 | .appendChild(node.cloneNode(true)); 32 | }; 33 | -------------------------------------------------------------------------------- /packages/stockflux-launcher/src/search-results/messages.js: -------------------------------------------------------------------------------- 1 | export default { 2 | NO_MATCHES: 'Sorry, no matches found.', 3 | INITIAL: 4 | 'Use the input field above to search for instruments or click on the search icon to close the search.' 5 | }; 6 | -------------------------------------------------------------------------------- /packages/stockflux-launcher/src/toolbar/CloseButton.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Components from 'stockflux-components'; 3 | import { OpenfinApiHelpers } from 'stockflux-core'; 4 | 5 | export default ( 6 | OpenfinApiHelpers.getCurrentWindowSync().close()} 9 | > 10 | 11 | 12 | ); 13 | -------------------------------------------------------------------------------- /packages/stockflux-launcher/src/toolbar/ToolBar.css: -------------------------------------------------------------------------------- 1 | .toolbar { 2 | display: flex; 3 | align-items: center; 4 | } 5 | 6 | .t-vertical { 7 | margin-bottom: 12px; 8 | } 9 | 10 | .left .toolbar, 11 | .right .toolbar { 12 | flex-direction: column; 13 | } 14 | 15 | .left .toolbar button, 16 | .right .toolbar button { 17 | margin: 5px 0; 18 | } 19 | 20 | .toolbar button svg { 21 | margin-top: 15px; 22 | padding: 0; 23 | } 24 | 25 | .dropdown-vertical { 26 | display: flex; 27 | flex-direction: column; 28 | overflow:hidden; 29 | } 30 | 31 | .dropdown-horizontal { 32 | margin-top:3px; 33 | display: flex; 34 | flex-direction: row; 35 | height:100%; 36 | align-items: center; 37 | } 38 | 39 | .dropdown button{ 40 | display: flex; 41 | align-items: center; 42 | box-sizing: border-box; 43 | height: 45px; 44 | width: 86px; 45 | margin-left:5px; 46 | margin-right:5px; 47 | border: 1px transparent; 48 | border-radius: 4px; 49 | } 50 | 51 | .dropdown :disabled{ 52 | display: flex; 53 | align-items: center; 54 | box-sizing: border-box; 55 | color:white !important; 56 | border: 1px solid #FFFFFF !important; 57 | background-color: #091A29 !important; 58 | } 59 | 60 | .dropdown :hover{ 61 | display: flex; 62 | color:white !important; 63 | align-items: center; 64 | box-sizing: border-box; 65 | border: 1px solid black; 66 | background-color: #091A29; 67 | } 68 | -------------------------------------------------------------------------------- /packages/stockflux-launcher/src/toolbar/ToolBar.js: -------------------------------------------------------------------------------- 1 | import cx from 'classnames'; 2 | import React from 'react'; 3 | import Components from 'stockflux-components'; 4 | import './ToolBar.css'; 5 | 6 | export default ({ tools, style }) => { 7 | return ( 8 |
9 | {tools 10 | .filter(tool => tool.visible) 11 | .map((tool, index) => ( 12 | tool.onClick()} 15 | disabled={!!tool.disabled} 16 | className={cx({ [tool.className]: tool.className })} 17 | > 18 | {tool.label} 19 | {tool.description} 20 | 21 | ))} 22 |
23 | ); 24 | }; 25 | -------------------------------------------------------------------------------- /packages/stockflux-news/README.md: -------------------------------------------------------------------------------- 1 | ## StockFlux News 2 | 3 | StockFlux News is a part of StockFlux app suite intended to work with StockFlux Launcher, Chart, and Watchlist apps. 4 | News is an app used to search for news stories related to a symbol. Each news story can be clicked on and will open in a secure iFrame that has no access to the Openfin API. 5 | 6 | ### Launching StockFlux News app from the installer 7 | 8 | Download the [installer](https://install.openfin.co/download/?os=win&config=https%3A%2F%2Fstockflux.scottlogic.com%2Fapi%2Fapps%2Fv1%2Fstockflux-launcher%2Fapp.json&fileName=stockflux&unzipped=true). After installing `StockFlux Launcher` icon should appear on the desktop. Double click it to open the StockFlux Launcher. 9 | 10 | StockFlux News can be launched from the launcher app: 11 | 12 | - by clicking on StockFlux News app icon in the top left corner of the launcher 13 | - by searching for a symbol using launcher's input field. When the list of symbols loads, click on the news icon of a particular symbol and that will open a new instance of the news app and search for stories related to that symbol. 14 | 15 | ### Running locally 16 | 17 | In order to launch the StockFlux News app locally, StockFlux Core and StockFlux Components have to be built first. 18 | Run the following commands in the root package to make lerna do the heavy lifting for you: 19 | 20 | ```bash 21 | npm install 22 | npm run bootstrap 23 | npm run build 24 | ``` 25 | 26 | 27 | To start and launch the StockFlux News: 28 | 29 | ```bash 30 | npm start 31 | npm run launch 32 | ``` 33 | 34 | Unfortunately at the time of writing, the news application will only search for a symbol if it is provided over the Openfin InterApplicationBus. 35 | Work is planned to include a search bar to allow the application to function standalone. 36 | 37 | To launch other StockFlux apps locally read the `README.md` files in the project folders. 38 | -------------------------------------------------------------------------------- /packages/stockflux-news/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "stockflux-news", 3 | "version": "13.1.1", 4 | "private": true, 5 | "dependencies": { 6 | "date-fns": "^1.30.1", 7 | "openfin-fdc3": "^0.1.1", 8 | "openfin-layouts": "^1.0.0", 9 | "openfin-react-hooks": "^1.3.3", 10 | "prop-types": "15.7.2", 11 | "react": "^16.8.6", 12 | "react-dom": "^16.8.6", 13 | "react-icons": "^3.7.0", 14 | "react-scripts": "3.0.1", 15 | "stockflux-components": "13.1.1", 16 | "stockflux-core": "13.1.1", 17 | "throat": "^5.0.0" 18 | }, 19 | "devDependencies": { 20 | "cross-env": "^5.2.0", 21 | "openfin-cli": "^2.0.9" 22 | }, 23 | "homepage": "./", 24 | "scripts": { 25 | "start": "cross-env BROWSER=none PORT=8056 react-scripts start", 26 | "build": "react-scripts build", 27 | "launch": "openfin --launch --config ./public/app.dev.json", 28 | "launch-appd": "openfin --launch --config http://localhost:3000/api/apps/v1/stockflux-news/app.json", 29 | "test": "react-scripts test", 30 | "eject": "react-scripts eject" 31 | }, 32 | "browserslist": [ 33 | "chrome 68" 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /packages/stockflux-news/public/app.dev.json: -------------------------------------------------------------------------------- 1 | { 2 | "devtools_port": 9091, 3 | "runtime": { 4 | "arguments": "--enable-aggressive-domstorage-flushing", 5 | "version": "12.69.43.22" 6 | }, 7 | "startup_app": { 8 | "name": "stockflux-news", 9 | "uuid": "stockflux-news", 10 | "url": "http://localhost:8056/index.html", 11 | "applicationIcon": "http://localhost:8056/favicon.ico", 12 | "autoShow": true, 13 | "maxHeight": 400, 14 | "defaultWidth": 400, 15 | "minWidth": 400, 16 | "maxWidth": 400, 17 | "resizable": false, 18 | "frame": false, 19 | "contextMenu": true, 20 | "cornerRounding": { 21 | "height": 4, 22 | "width": 4 23 | }, 24 | "customData": { 25 | "apiBaseUrl": "http://localhost:3010/api" 26 | } 27 | }, 28 | "services": [ 29 | { 30 | "name": "layouts", 31 | "config": { 32 | "features": { 33 | "tab": false 34 | } 35 | } 36 | } 37 | ], 38 | "shortcut": { 39 | "company": "ScottLogic", 40 | "description": "Hosts StockFlux News as an OpenFin application.", 41 | "name": "StockFlux News", 42 | "icon": "http://localhost:8056/favicon.ico" 43 | }, 44 | "splashScreenImage": "http://localhost:8056/splashscreen.png" 45 | } -------------------------------------------------------------------------------- /packages/stockflux-news/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/packages/stockflux-news/public/favicon.ico -------------------------------------------------------------------------------- /packages/stockflux-news/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | StockFlux News 10 | 11 | 12 | 13 |
14 | 15 | 16 | -------------------------------------------------------------------------------- /packages/stockflux-news/public/launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/packages/stockflux-news/public/launcher.png -------------------------------------------------------------------------------- /packages/stockflux-news/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "Stockflux News", 3 | "name": "Stockflux News", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": ".", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /packages/stockflux-news/public/splashscreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/packages/stockflux-news/public/splashscreen.png -------------------------------------------------------------------------------- /packages/stockflux-news/src/App.css: -------------------------------------------------------------------------------- 1 | .stockflux-news { 2 | height: 100%; 3 | background-color: var(--window-background-color-dark); 4 | } 5 | 6 | .container { 7 | max-height: 700px; 8 | height: calc(100vh - var(--titlebar-height)); 9 | } 10 | 11 | .icons { 12 | white-space: nowrap; 13 | } 14 | 15 | .no-articles { 16 | padding: var(--padding-medium); 17 | display: flex; 18 | height: var(--no-article-height); 19 | justify-content: center; 20 | font-size: var(--font-large); 21 | color: var(--text-grey-lighter); 22 | font-weight: var(--font-weight-bold); 23 | } 24 | 25 | .spin-container { 26 | padding: var(--padding-medium) 0; 27 | height: 46px; 28 | } -------------------------------------------------------------------------------- /packages/stockflux-news/src/components/news-item/NewsItem.css: -------------------------------------------------------------------------------- 1 | .newsitem { 2 | display: flex; 3 | max-height: var(--newsitem-height); 4 | color: white; 5 | cursor: pointer; 6 | flex-direction: column; 7 | padding: var(--padding-medium); 8 | border-bottom: 4px solid var(--window-divider); 9 | } 10 | 11 | .newsitem:hover { 12 | background-color: var(--color-hover); 13 | } 14 | 15 | .source { 16 | font-size: var(--font-small); 17 | display: flex; 18 | justify-content: center; 19 | color: #9e9e9e; 20 | padding-right: var(--padding-small); 21 | padding-top: var(--padding-small); 22 | } 23 | 24 | .newsitem-content { 25 | padding-top: var(--padding-medium); 26 | width: 100%; 27 | max-height: 80px; 28 | overflow: hidden; 29 | text-overflow: ellipsis; 30 | display: -webkit-box; 31 | -webkit-line-clamp: 2; 32 | -webkit-box-orient: vertical; 33 | font-weight: var(--font-weight-re); 34 | } 35 | 36 | .headline { 37 | font-size: var(--font-xlarge); 38 | text-transform: capitalize; 39 | font-weight: var(--font-weight-medium); 40 | color: white; 41 | width: 70%; 42 | min-width: 0; 43 | text-overflow: ellipsis; 44 | overflow: hidden; 45 | display: -webkit-box; 46 | -webkit-line-clamp: 2; 47 | -webkit-box-orient: vertical; 48 | } 49 | 50 | .newsitem-header { 51 | display: flex; 52 | flex-direction: row; 53 | justify-content: space-between; 54 | width: 100%; 55 | height: 40px; 56 | } 57 | 58 | .summary { 59 | font-size: var(--font-normal); 60 | overflow: hidden; 61 | text-overflow: ellipsis; 62 | display: -webkit-box; 63 | -webkit-line-clamp: 2; 64 | -webkit-box-orient: vertical; 65 | } 66 | 67 | .newsitem-meta { 68 | display: flex; 69 | flex-direction: row; 70 | overflow: hidden; 71 | padding-top: var(--padding-small); 72 | } 73 | -------------------------------------------------------------------------------- /packages/stockflux-news/src/components/news-item/NewsItem.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { format, isToday } from 'date-fns'; 3 | import * as PropTypes from 'prop-types'; 4 | 5 | import './NewsItem.css'; 6 | 7 | const handleNewsItemClick = link => { 8 | window.fin.System.openUrlWithBrowser(link); 9 | }; 10 | 11 | const articleDate = unformattedDate => { 12 | const date = new Date(unformattedDate); 13 | return !isToday(date) 14 | ? format(date, 'DD MMM') 15 | : format(date, 'DD MMM h:mm A'); 16 | }; 17 | 18 | const NewsItem = ({ headline, source, copy, link, time }) => ( 19 |
handleNewsItemClick(link)}> 20 |
21 |
{headline}
22 |
{articleDate(time)}
23 |
24 |
25 |
{source}
26 |
27 |
28 |
{copy}
29 |
30 |
31 | ); 32 | 33 | NewsItem.propTypes = { 34 | headline: PropTypes.string.isRequired, 35 | source: PropTypes.string.isRequired, 36 | copy: PropTypes.string.isRequired, 37 | time: PropTypes.number.isRequired 38 | }; 39 | 40 | export default NewsItem; 41 | -------------------------------------------------------------------------------- /packages/stockflux-news/src/components/news-item/index.js: -------------------------------------------------------------------------------- 1 | export { default } from './NewsItem'; 2 | -------------------------------------------------------------------------------- /packages/stockflux-news/src/index.css: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | color: var(--text-color); 4 | } 5 | 6 | body { 7 | height: 100%; 8 | margin: 0; 9 | overflow: hidden; 10 | } 11 | 12 | #root { 13 | height: 100%; 14 | --header-height: 60px; 15 | --tabbar-height: 36px; 16 | --newsitem-height: 143px; 17 | --no-article-height: 30px; 18 | } -------------------------------------------------------------------------------- /packages/stockflux-news/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import * as serviceWorker from './serviceWorker'; 6 | 7 | ReactDOM.render(, document.getElementById('root')); 8 | 9 | // If you want your app to work offline and load faster, you can change 10 | // unregister() to register() below. Note this comes with some pitfalls. 11 | // Learn more about service workers: https://bit.ly/CRA-PWA 12 | serviceWorker.unregister(); 13 | -------------------------------------------------------------------------------- /packages/stockflux-watchlist/README.md: -------------------------------------------------------------------------------- 1 | ## StockFlux Watchlist 2 | 3 | StockFlux Watchlist is a part of StockFlux app suite intended to work with StockFlux Launcher, Chart, and News apps. 4 | Watchlist is an app containing the list of symbols the user is watching. These symbols are displayed as cards containing key symbol information and a minichart of the symbol's price fluctuations in the last 30 days. 5 | 6 | ### Launching StockFlux Watchlist app from the installer 7 | 8 | Download the [installer](https://install.openfin.co/download/?os=win&config=https%3A%2F%2Fstockflux.scottlogic.com%2Fapi%2Fapps%2Fv1%2Fstockflux-launcher%2Fapp.json&fileName=stockflux&unzipped=true). After installing `StockFlux Launcher` icon should appear on the desktop. Double click it to open the StockFlux Launcher. 9 | 10 | StockFlux Watchlist can be launched from the launcher app: 11 | 12 | - by clicking on StockFlux Watchlist app icon in the top left corner of the launcher 13 | - by searching for a symbol using launcher's input field. When the list of symbols loads, click on the watchlist icon of a particular symbol and that symbol will be added to the watchlist subsequently launching the Watchlist app. 14 | 15 | ### Watchlist card functionality 16 | 17 | - Dragging and dropping a Watchlist card outside the Watchlist borders opens the StockFlux Chart app for that symbol. 18 | - Clicking on a minichart in the Watchlist card also opens the StockFlux Chart app for that symbol. 19 | - Each card has a News app icon, clicking on it opens the list of news regarding that symbol. 20 | - Each card also has the `X` icon, clicking on it removes the symbol from the watchlist. 21 | 22 | ### Running locally 23 | 24 | In order to launch the StockFlux Watchlist app locally, StockFlux Core and StockFlux Components have to be built first. 25 | Run the following commands in the root package to make lerna do the heavy lifting for you: 26 | 27 | ```bash 28 | npm install 29 | npm run bootstrap 30 | npm run build 31 | ``` 32 | 33 | To start and launch the StockFlux Watchlist: 34 | 35 | ```bash 36 | npm start 37 | npm run launch 38 | ``` 39 | 40 | To launch other StockFlux apps locally read the `README.md` files in the project folders. 41 | -------------------------------------------------------------------------------- /packages/stockflux-watchlist/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "stockflux-watchlist", 3 | "version": "13.1.1", 4 | "private": true, 5 | "dependencies": { 6 | "classnames": "^2.2.6", 7 | "d3-scale": "^2.1.2", 8 | "d3-selection": "^1.3.2", 9 | "d3fc": "^14.0.21", 10 | "date-fns": "1.30.1", 11 | "openfin-fdc3": "^0.1.1", 12 | "openfin-layouts": "^1.0.0", 13 | "openfin-react-hooks": "^1.3.3", 14 | "react": "^16.8.6", 15 | "react-dom": "^16.8.6", 16 | "react-icons": "^3.7.0", 17 | "react-scripts": "3.0.1", 18 | "stockflux-components": "13.1.1", 19 | "stockflux-core": "13.1.1" 20 | }, 21 | "homepage": "./", 22 | "scripts": { 23 | "start": "cross-env BROWSER=none PORT=8052 react-scripts start", 24 | "launch": "openfin --launch --config ./public/app.dev.json", 25 | "launch-appd": "openfin --launch --config http://localhost:3000/api/apps/v1/stockflux-watchlist/app.json", 26 | "build": "react-scripts build", 27 | "test": "react-scripts test", 28 | "eject": "react-scripts eject" 29 | }, 30 | "browserslist": [ 31 | "chrome 68" 32 | ], 33 | "devDependencies": { 34 | "cross-env": "^5.2.0", 35 | "openfin-cli": "^2.0.8" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /packages/stockflux-watchlist/public/ArrowUp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/packages/stockflux-watchlist/public/ArrowUp.png -------------------------------------------------------------------------------- /packages/stockflux-watchlist/public/CardIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/packages/stockflux-watchlist/public/CardIcon.png -------------------------------------------------------------------------------- /packages/stockflux-watchlist/public/app.dev.json: -------------------------------------------------------------------------------- 1 | { 2 | "devtools_port": 9090, 3 | "runtime": { 4 | "arguments": "--enable-aggressive-domstorage-flushing", 5 | "version": "12.69.43.22" 6 | }, 7 | "startup_app": { 8 | "name": "stockflux-watchlist", 9 | "uuid": "33aa9062-9eb0-4875-b819-c90f38ef0999", 10 | "url": "http://localhost:8052/index.html", 11 | "applicationIcon": "http://localhost:8052/favicon.ico", 12 | "autoShow": true, 13 | "defaultWidth": 230, 14 | "defaultHeight": 600, 15 | "maxWidth": 230, 16 | "minWidth": 230, 17 | "minHeight": 300, 18 | "frame": false, 19 | "contextMenu": true, 20 | "customData": { 21 | "apiBaseUrl": "https://d3capoqa8f983r.cloudfront.net/api" 22 | } 23 | }, 24 | "services": [ 25 | { 26 | "name": "layouts", 27 | "config": { 28 | "features": { 29 | "tab": false 30 | } 31 | } 32 | } 33 | ], 34 | "shortcut": { 35 | "company": "ScottLogic", 36 | "description": "Hosts StockFlux Watchlist as an OpenFin application.", 37 | "name": "StockFlux Watchlist", 38 | "icon": "http://localhost:8052/favicon.ico" 39 | }, 40 | "splashScreenImage": "http://localhost:8052/splashscreen.png" 41 | } 42 | -------------------------------------------------------------------------------- /packages/stockflux-watchlist/public/child-window.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | -------------------------------------------------------------------------------- /packages/stockflux-watchlist/public/childWindow.css: -------------------------------------------------------------------------------- 1 | body { 2 | overflow-x: hidden; 3 | height: inherit; 4 | } 5 | 6 | div#root { 7 | height:100vh; 8 | flex: 1 1 auto; 9 | overflow:hidden; 10 | } 11 | 12 | div.scrollWrapperY > p { 13 | text-align: center; 14 | color: var(--text-grey-light); 15 | padding: 170px 50px; 16 | font-weight: var(--font-weight-bold); 17 | letter-spacing: 0.2px; 18 | margin: 0; 19 | } 20 | 21 | .spinner { 22 | position: relative; 23 | top:calc(50vh - var(--search-input-height)) 24 | } 25 | 26 | .card { 27 | padding: var(--padding-medium); 28 | display: flex; 29 | align-items: center; 30 | justify-content: space-between; 31 | border-bottom: 1px solid var(--clr-divider-light); 32 | } 33 | 34 | .card p { 35 | cursor: default; 36 | margin: var(--margin-medium); 37 | } 38 | 39 | div#actions { 40 | float: right; 41 | margin: 0 var(--margin-small); 42 | display: inherit; 43 | } 44 | 45 | .card:hover { 46 | background-color: var(--dark-background); 47 | } 48 | 49 | .name { 50 | letter-spacing: 0.5px; 51 | font-weight: var(--font-weight-bold); 52 | color: var(--text-teal-light); 53 | } 54 | .symbol { 55 | letter-spacing: 1px; 56 | font-size: var(--font-xlarge); 57 | font-weight: var(--font-weight-bolder); 58 | color: var(--text-grey-lighter); 59 | } 60 | -------------------------------------------------------------------------------- /packages/stockflux-watchlist/public/delete-symbol.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 31 | 32 | 33 | 34 |
35 |
36 |

Drag Outside Window To Delete

37 |
38 |
39 | 40 | 41 | -------------------------------------------------------------------------------- /packages/stockflux-watchlist/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/packages/stockflux-watchlist/public/favicon.ico -------------------------------------------------------------------------------- /packages/stockflux-watchlist/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 10 | 11 | 12 | StockFlux - Watchlist 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | -------------------------------------------------------------------------------- /packages/stockflux-watchlist/public/launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/packages/stockflux-watchlist/public/launcher.png -------------------------------------------------------------------------------- /packages/stockflux-watchlist/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "StockFlux Watchlist", 3 | "name": "StockFlux Watchlist App", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": ".", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /packages/stockflux-watchlist/public/notification.css: -------------------------------------------------------------------------------- 1 | @import url(https://fonts.googleapis.com/css?family=Roboto:400, 100, 300, 500); 2 | 3 | div#root { 4 | background-color: var(--window-background-color); 5 | height: 100vh; 6 | overflow: hidden; 7 | display: inline-flex; 8 | } 9 | 10 | body { 11 | border: none; 12 | border-left: 5px solid #21b1ca; 13 | } 14 | 15 | .notification > * { 16 | margin-top: auto; 17 | margin-bottom: auto; 18 | } 19 | 20 | .notification .icon { 21 | margin: auto 20px; 22 | height: 28px; 23 | width: 57px; 24 | animation: eyeGif 1.5s steps(45, end) 1s forwards; 25 | background: url('./animation-assets/eye_outline_animation_long.svg') 0 0 26 | no-repeat; 27 | } 28 | 29 | p { 30 | padding-right: var(--padding-large); 31 | } 32 | 33 | @keyframes eyeGif { 34 | 0% { 35 | background-position: 0 0; 36 | } 37 | 100% { 38 | background-position: -2250px 0; 39 | } 40 | } 41 | 42 | .notification { 43 | display: flex; 44 | } 45 | -------------------------------------------------------------------------------- /packages/stockflux-watchlist/public/notification.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | -------------------------------------------------------------------------------- /packages/stockflux-watchlist/public/popupWindow.css: -------------------------------------------------------------------------------- 1 | body { 2 | overflow: hidden; 3 | padding: 4vh 4vw; 4 | border:var(--border); 5 | box-sizing: border-box; 6 | } 7 | .popup{ 8 | color:var(--text-grey-lighter); 9 | } 10 | 11 | .popup-message{ 12 | text-align: center; 13 | font-size: var(--font-large); 14 | } 15 | 16 | .popup-options { 17 | text-align: right; 18 | } 19 | 20 | .popup-options button { 21 | color:var(--text-teal-light); 22 | border-color:var(--text-teal-light); 23 | } -------------------------------------------------------------------------------- /packages/stockflux-watchlist/public/preview-chart.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 33 | 34 | 35 | 36 |
37 |
38 |

Drag here to
open a chart

39 | 40 | 41 | 42 |
43 |
44 | 45 | 46 | -------------------------------------------------------------------------------- /packages/stockflux-watchlist/public/splashscreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/packages/stockflux-watchlist/public/splashscreen.png -------------------------------------------------------------------------------- /packages/stockflux-watchlist/src/components/PreviewOptions.js: -------------------------------------------------------------------------------- 1 | export default { none: '', chart: 'CHART', delete: 'DELETE' }; 2 | -------------------------------------------------------------------------------- /packages/stockflux-watchlist/src/components/minichart/Minichart.css: -------------------------------------------------------------------------------- 1 | .overflow, 2 | .minichart, 3 | .minichart svg { 4 | overflow: visible; 5 | } 6 | 7 | .minichart { 8 | width: var(--minichart-width); 9 | height: var(--minichart-height); 10 | pointer-events: none; 11 | z-index: 1; 12 | } 13 | 14 | g { 15 | fill: var(--middle-background); 16 | } 17 | 18 | path.line { 19 | stroke: var( --chart-line); 20 | } 21 | 22 | .point { 23 | fill: var(--chart-line); 24 | stroke: var( --chart-line); 25 | } 26 | 27 | .top { 28 | stop-color: var( --chart-line); 29 | stop-opacity: 0.2; 30 | } 31 | 32 | .bottom { 33 | stop-color: var( --chart-line); 34 | stop-opacity: 0.2; 35 | } 36 | 37 | .minichart-error { 38 | padding: 5px 3px; 39 | font-size: var(--font-normal); 40 | font-weight: var(--font-weight-normal); 41 | color: var(--text-grey-lighter); 42 | padding-left: var(--padding-medium); 43 | width: 160px; 44 | } -------------------------------------------------------------------------------- /packages/stockflux-watchlist/src/components/minichart/constants.js: -------------------------------------------------------------------------------- 1 | // Minichart Dimensions in px 2 | const WIDTH = 271; 3 | const HEIGHT = 49; 4 | const PADDING_LEFT = 0; 5 | const PADDING_RIGHT = 0; 6 | const PADDING_TOP = 0; 7 | const PADDING_BOTTOM = 0; 8 | 9 | export const minichartDimensions = { 10 | WIDTH, 11 | HEIGHT, 12 | PADDING_BOTTOM, 13 | PADDING_TOP, 14 | PADDING_LEFT, 15 | PADDING_RIGHT 16 | }; 17 | -------------------------------------------------------------------------------- /packages/stockflux-watchlist/src/icons/chart.svg: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /packages/stockflux-watchlist/src/icons/news.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Glyph/24News 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /packages/stockflux-watchlist/src/icons/watchlist.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Glyph/24Watchlist 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /packages/stockflux-watchlist/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import { OpenfinApiHelpers } from 'stockflux-core'; 4 | import App from './App'; 5 | 6 | const mountApp = () => { 7 | ReactDOM.render(, document.getElementById('root')); 8 | }; 9 | 10 | if (OpenfinApiHelpers.getWindow()) { 11 | OpenfinApiHelpers.useMain(mountApp); 12 | } else { 13 | console.error('This application can only be run in an OpenFin container.'); 14 | } 15 | -------------------------------------------------------------------------------- /packages/stockflux-watchlist/src/reducers/open-apps/Action.js: -------------------------------------------------------------------------------- 1 | export default { 2 | SET_CHART_WINDOW: 'SET_CHART_WINDOW', 3 | SET_NEWS_WINDOW: 'SET_NEWS_WINDOW', 4 | RESET: 'RESET' 5 | }; 6 | -------------------------------------------------------------------------------- /packages/stockflux-watchlist/src/reducers/open-apps/OpenApps.js: -------------------------------------------------------------------------------- 1 | import ActionType from './Action'; 2 | 3 | export const initialState = { 4 | chart: false, 5 | news: false 6 | }; 7 | 8 | export default (state, { type, payload }) => { 9 | switch (type) { 10 | case ActionType.SET_CHART_WINDOW: 11 | return { 12 | ...state, 13 | chart: payload 14 | }; 15 | case ActionType.SET_NEWS_WINDOW: 16 | return { 17 | ...state, 18 | news: payload 19 | }; 20 | case ActionType.RESET: 21 | return initialState; 22 | default: 23 | throw new Error(); 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /packages/stockflux-watchlist/src/services/currentWindowService.js: -------------------------------------------------------------------------------- 1 | import { OpenfinApiHelpers } from 'stockflux-core'; 2 | 3 | /** 4 | * Abstraction layer for the OpenFin API. 5 | */ 6 | class CurrentWindowService { 7 | getCurrentWindow() { 8 | return OpenfinApiHelpers.getCurrentWindow(); 9 | } 10 | 11 | getCurrentWindowName() { 12 | return this.getCurrentWindow().name; 13 | } 14 | 15 | ready(cb) { 16 | OpenfinApiHelpers.useMain(cb); 17 | } 18 | 19 | openUrlWithBrowser(url) { 20 | OpenfinApiHelpers.openUrlWithBrowser(url); 21 | } 22 | 23 | resizeTo(...args) { 24 | return this.getCurrentWindow().resizeTo(...args); 25 | } 26 | 27 | updateOptions(...args) { 28 | return this.getCurrentWindow().updateOptions(...args); 29 | } 30 | } 31 | 32 | export default new CurrentWindowService(); 33 | -------------------------------------------------------------------------------- /stockflux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ScottLogic/StockFlux/9357b5cc65e14e4d9f3351a10aa53c68b249b53a/stockflux.png --------------------------------------------------------------------------------