├── .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 |
--------------------------------------------------------------------------------
/assets/arrows/Price_Arrow_Up.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/assets/glyphs v1/24px/Glyph_Chart_Compressed.svg:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/assets/glyphs v1/24px/Glyph_Left 24px.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/assets/glyphs v1/24px/Glyph_News 24px.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/assets/glyphs v1/24px/Glyph_News_Compressed.svg:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/assets/glyphs v1/24px/Glyph_Right 24px.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/assets/glyphs v1/24px/Glyph_Search 24px.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/assets/glyphs v1/24px/Glyph_Top 24px.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/assets/glyphs v1/24px/Glyph_Watchlist 24px.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/assets/glyphs v1/24px/Glyph_Watchlist_Compressed.svg:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/assets/glyphs v1/30px/Glyph_Chart 30px.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/assets/glyphs v1/30px/Glyph_Closesvg.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/assets/glyphs v1/30px/Glyph_Drag 30px.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/assets/glyphs v1/30px/Glyph_Left 30px.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/assets/glyphs v1/30px/Glyph_Minimize.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/assets/glyphs v1/30px/Glyph_News 30px.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/assets/glyphs v1/30px/Glyph_Right 30px.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/assets/glyphs v1/30px/Glyph_Search 30px.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/assets/glyphs v1/30px/Glyph_Top 30px.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/assets/glyphs v1/30px/Glyph_Watchlist 30px.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/assets/icons v1/Icon_Pin.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/assets/logos/D3FC Logo.svg:
--------------------------------------------------------------------------------
1 |
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 |
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 |
--------------------------------------------------------------------------------
/packages/stockflux-components/src/components/glyphs/arrows/priceArrowUp.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/stockflux-components/src/components/glyphs/launcher/left.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/stockflux-components/src/components/glyphs/launcher/right.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/stockflux-components/src/components/glyphs/launcher/search.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/stockflux-components/src/components/glyphs/launcher/top.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/stockflux-components/src/components/glyphs/launcher/watchlist.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/stockflux-components/src/components/glyphs/normal/chart.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/stockflux-components/src/components/glyphs/normal/watchlist.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/stockflux-components/src/components/glyphs/small/chart.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/stockflux-components/src/components/glyphs/small/hide.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/stockflux-components/src/components/glyphs/small/remove.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/stockflux-components/src/components/glyphs/small/reveal.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/stockflux-components/src/components/glyphs/small/watchlist.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/stockflux-components/src/components/icons/chart.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/stockflux-components/src/components/icons/close.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/packages/stockflux-components/src/components/icons/link.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/packages/stockflux-components/src/components/icons/minimize.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/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 |
27 |
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 |
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 |
--------------------------------------------------------------------------------
/packages/stockflux-watchlist/src/icons/news.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/packages/stockflux-watchlist/src/icons/watchlist.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/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
--------------------------------------------------------------------------------