diff --git a/src/store/ChartStore.js b/src/store/ChartStore.js index 4513651a92..fb53ab2ec4 100644 --- a/src/store/ChartStore.js +++ b/src/store/ChartStore.js @@ -1,6 +1,5 @@ import ResizeObserver from 'resize-observer-polyfill'; import { action, observable, reaction, computed } from 'mobx'; -import { CIQ, SplinePlotter } from 'chartiq'; import PendingPromise from '../utils/PendingPromise'; import Context from '../components/ui/Context'; import KeystrokeHub from '../components/ui/KeystrokeHub'; @@ -10,8 +9,7 @@ import { Feed } from '../feed'; import { ActiveSymbols, BinaryAPI, TradingTimes } from '../binaryapi'; import { calculateTimeUnitInterval, getUTCDate, cloneCategories } from '../utils'; -window.CIQ = CIQ; -CIQ.ChartEngine.prototype.createYAxisLabel = function (panel, txt, y, backgroundColor, color, ctx, yAxis) { +function myCreateYAxisLabel(panel, txt, y, backgroundColor, color, ctx, yAxis) { if (panel.yAxis.drawPriceLabels === false || panel.yAxis.noDraw) return; const yax = yAxis || panel.yAxis; if (yax.noDraw || !yax.width) return; @@ -68,7 +66,7 @@ CIQ.ChartEngine.prototype.createYAxisLabel = function (panel, txt, y, background color, }; CIQ[yaxisLabelStyle](params); -}; +} class ChartStore { static keystrokeHub; @@ -142,153 +140,158 @@ class ChartStore { setTimeout(this.updateCanvas, this.isMobile ? 500 : 100); } - @action.bound init(rootNode, modalNode, props) { - SplinePlotter.plotSpline = plotSpline; - this.rootNode = rootNode; - this.modalNode = modalNode; - this.chartNode = this.rootNode.querySelector('.ciq-chart-area'); - this.chartControlsNode = this.rootNode.querySelector('.cq-chart-controls'); - - const { - symbol, - chartType, - granularity, - requestAPI, - requestSubscribe, - requestForget, - isMobile, - enableRouting, - onMessage, - settings, - onSettingsChange, - } = props; - this.api = new BinaryAPI(requestAPI, requestSubscribe, requestForget); - this.tradingTimes = new TradingTimes(this.api); - this.activeSymbols = new ActiveSymbols(this.api, this.tradingTimes); - const { chartSetting } = this.mainStore; - chartSetting.setSettings(settings); - chartSetting.onSettingsChange = onSettingsChange; - this.isMobile = isMobile; - this.state = this.mainStore.state; - - this.mainStore.notifier.onMessage = onMessage; - this.granularity = (granularity !== undefined) ? granularity : this.defaults.granularity; - const engineParams = { - maxMasterDataSize: 5000, // cap size so tick_history requests do not become too large - markerDelay: null, // disable 25ms delay for placement of markers - container: this.rootNode.querySelector('.chartContainer'), - controls: { chartControls: null }, // hide the default zoom buttons - preferences: { - currentPriceLine: true, - whitespace: isMobile ? 50 : 150, - }, - chart: { - yAxis: { - // Put some top margin so chart doesn't get blocked by chart title - initialMarginTop: 125, - initialMarginBottom: 10, - // position: 'left', - width: -10, - justifyRight: true, + init = (rootNode, modalNode, props) => { + import(/* webpackChunkName: "chartiq" */ 'chartiq').then(action(({ CIQ, SplinePlotter }) => { + window.CIQ = CIQ; + CIQ.ChartEngine.prototype.createYAxisLabel = myCreateYAxisLabel; + SplinePlotter.plotSpline = plotSpline; + + this.rootNode = rootNode; + this.modalNode = modalNode; + this.chartNode = this.rootNode.querySelector('.ciq-chart-area'); + this.chartControlsNode = this.rootNode.querySelector('.cq-chart-controls'); + + const { + symbol, + chartType, + granularity, + requestAPI, + requestSubscribe, + requestForget, + isMobile, + enableRouting, + onMessage, + settings, + onSettingsChange, + } = props; + this.api = new BinaryAPI(requestAPI, requestSubscribe, requestForget); + this.tradingTimes = new TradingTimes(this.api); + this.activeSymbols = new ActiveSymbols(this.api, this.tradingTimes); + const { chartSetting } = this.mainStore; + chartSetting.setSettings(settings); + chartSetting.onSettingsChange = onSettingsChange; + this.isMobile = isMobile; + this.state = this.mainStore.state; + + this.mainStore.notifier.onMessage = onMessage; + this.granularity = (granularity !== undefined) ? granularity : this.defaults.granularity; + const engineParams = { + maxMasterDataSize: 5000, // cap size so tick_history requests do not become too large + markerDelay: null, // disable 25ms delay for placement of markers + container: this.rootNode.querySelector('.chartContainer'), + controls: { chartControls: null }, // hide the default zoom buttons + preferences: { + currentPriceLine: true, + whitespace: isMobile ? 50 : 150, }, - }, - minimumLeftBars: 2, - yTolerance: 999999, // disable vertical scrolling - }; - let chartLayout = { - chartType: chartType || this.defaults.chartType, - }; - if (chartLayout.chartType === 'spline') { // cause there's no such thing as spline chart in ChartIQ - chartLayout.chartType = 'mountain'; - engineParams.chart.tension = chartLayout.tension = 0.5; - } - const rangeSpan = this.getRangeSpan(); - if (rangeSpan) { - chartLayout = { ...chartLayout, ...rangeSpan }; - } - engineParams.layout = chartLayout; - - const stxx = this.stxx = new CIQ.ChartEngine(engineParams); + chart: { + yAxis: { + // Put some top margin so chart doesn't get blocked by chart title + initialMarginTop: 125, + initialMarginBottom: 10, + // position: 'left', + width: -10, + justifyRight: true, + }, + }, + minimumLeftBars: 2, + yTolerance: 999999, // disable vertical scrolling + }; + let chartLayout = { + chartType: chartType || this.defaults.chartType, + }; + if (chartLayout.chartType === 'spline') { // cause there's no such thing as spline chart in ChartIQ + chartLayout.chartType = 'mountain'; + engineParams.chart.tension = chartLayout.tension = 0.5; + } + const rangeSpan = this.getRangeSpan(); + if (rangeSpan) { + chartLayout = { ...chartLayout, ...rangeSpan }; + } + engineParams.layout = chartLayout; - const deleteElement = stxx.chart.panel.holder.parentElement.querySelector('.mouseDeleteText'); - const manageElement = stxx.chart.panel.holder.parentElement.querySelector('.mouseManageText'); - deleteElement.textConent = t.translate('right-click to delete'); - manageElement.textConent = t.translate('right-click to manage'); + const stxx = this.stxx = new CIQ.ChartEngine(engineParams); - animateChart(stxx, { stayPut: true }); + const deleteElement = stxx.chart.panel.holder.parentElement.querySelector('.mouseDeleteText'); + const manageElement = stxx.chart.panel.holder.parentElement.querySelector('.mouseManageText'); + deleteElement.textConent = t.translate('right-click to delete'); + manageElement.textConent = t.translate('right-click to manage'); - // connect chart to data - this.feed = new Feed(this.api, stxx, this.mainStore, this.tradingTimes); - stxx.attachQuoteFeed(this.feed, { - refreshInterval: null, - }); + animateChart(stxx, { stayPut: true }); - this.enableRouting = enableRouting; - if (this.enableRouting) { - this.routingStore.handleRouting(); - } + // connect chart to data + this.feed = new Feed(this.api, stxx, this.mainStore, this.tradingTimes); + stxx.attachQuoteFeed(this.feed, { + refreshInterval: null, + }); - this.holderStyle = stxx.chart.panel.holder.style; + this.enableRouting = enableRouting; + if (this.enableRouting) { + this.routingStore.handleRouting(); + } - const context = new Context(stxx, this.rootNode); + this.holderStyle = stxx.chart.panel.holder.style; - // only one instance of keystrokeHub should exist - if (ChartStore.keystrokeHub === undefined) { - ChartStore.keystrokeHub = new KeystrokeHub(document.body, context, { - cb: KeystrokeHub.defaultHotKeys, - }); - } + const context = new Context(stxx, this.rootNode); - // TODO: excluded studies + // only one instance of keystrokeHub should exist + if (ChartStore.keystrokeHub === undefined) { + ChartStore.keystrokeHub = new KeystrokeHub(document.body, context, { + cb: KeystrokeHub.defaultHotKeys, + }); + } - this.loader.show(); + // TODO: excluded studies - const studiesStore = this.mainStore.studies; - stxx.callbacks.studyOverlayEdit = studiesStore.editStudy; - stxx.callbacks.studyPanelEdit = studiesStore.editStudy; + this.loader.show(); - this.tradingTimes.initialize().then(() => { - this.activeSymbols.retrieveActiveSymbols().then(action(() => { - // In the odd event that chart is destroyed by the time - // the request finishes, just calmly return... - if (stxx.isDestroyed) { return; } + const studiesStore = this.mainStore.studies; + stxx.callbacks.studyOverlayEdit = studiesStore.editStudy; + stxx.callbacks.studyPanelEdit = studiesStore.editStudy; - const isRestoreSuccess = this.state.restoreLayout(); + this.tradingTimes.initialize().then(() => { + this.activeSymbols.retrieveActiveSymbols().then(action(() => { + // In the odd event that chart is destroyed by the time + // the request finishes, just calmly return... + if (stxx.isDestroyed) { return; } - if (!isRestoreSuccess) { - this.changeSymbol( - symbol || this.defaults.symbol, - this.granularity, - ); - } + const isRestoreSuccess = this.state.restoreLayout(); - this.context = context; - stxx.container.addEventListener('mouseenter', this.onMouseEnter); - stxx.container.addEventListener('mouseleave', this.onMouseLeave); - this.contextPromise.resolve(this.context); - this.resizeScreen(); - - reaction(() => [ - this.state.symbol, - this.state.granularity, - ], () => { - if (this.state.symbol !== undefined || this.state.granularity !== undefined) { - this.changeSymbol(this.state.symbol, this.state.granularity); + if (!isRestoreSuccess) { + this.changeSymbol( + symbol || this.defaults.symbol, + this.granularity, + ); } - }); - this.tradingTimes.onMarketOpenCloseChanged(this.onMarketOpenClosedChange); - - setTimeout(action(() => { - // Defer the render of the dialogs and dropdowns; this enables - // considerable performance improvements for slower devices. - this.shouldRenderDialogs = true; - }), 500); - })); - }); + this.context = context; + stxx.container.addEventListener('mouseenter', this.onMouseEnter); + stxx.container.addEventListener('mouseleave', this.onMouseLeave); + this.contextPromise.resolve(this.context); + this.resizeScreen(); + + reaction(() => [ + this.state.symbol, + this.state.granularity, + ], () => { + if (this.state.symbol !== undefined || this.state.granularity !== undefined) { + this.changeSymbol(this.state.symbol, this.state.granularity); + } + }); + + this.tradingTimes.onMarketOpenCloseChanged(this.onMarketOpenClosedChange); + + setTimeout(action(() => { + // Defer the render of the dialogs and dropdowns; this enables + // considerable performance improvements for slower devices. + this.shouldRenderDialogs = true; + }), 500); + })); + }); - this.resizeObserver = new ResizeObserver(this.resizeScreen); - this.resizeObserver.observe(modalNode); + this.resizeObserver = new ResizeObserver(this.resizeScreen); + this.resizeObserver.observe(modalNode); + })); } onMarketOpenClosedChange = (changes) => { diff --git a/webpack.config.js b/webpack.config.js index 875458dc8a..9e2c0535ca 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -4,16 +4,15 @@ const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPl const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const CopyWebpackPlugin = require('copy-webpack-plugin'); const StyleLintPlugin = require('stylelint-webpack-plugin'); -const UglifyJs = require('uglify-js'); -const write = require('write'); const production = process.env.NODE_ENV === 'production'; const isApp = process.env.BUILD_MODE === 'app'; const output = { - publicPath: '/dist/', + publicPath: './dist/', path: path.resolve(__dirname, 'dist'), filename: 'smartcharts.js', + chunkFilename: '[name]-[chunkhash:6].js', libraryExport: 'default', library: 'smartcharts', libraryTarget: 'umd', @@ -29,6 +28,9 @@ const config = { chartiq: path.resolve(__dirname, 'chartiq/chartiq.js'), }, }, + devServer: { + publicPath: '/dist/', + }, module: { rules: [ {