@@ -11,9 +11,15 @@ var _ = require('../../lib')._;
1111 * so it is centered over the plot rather than the whole viewport. It can be
1212 * dismissed by clicking Cancel, clicking the backdrop, or pressing Escape.
1313 *
14+ * By default the chart is uploaded to the configured plotlyServerURL. A
15+ * "Use a custom server URL" link reveals an editable "Server URL" field
16+ * pre-filled with that default; whatever the user leaves in the field when they
17+ * confirm becomes the destination, so a custom URL entered here overrides the
18+ * plotlyServerURL config for that upload.
19+ *
1420 * @param {DOM node } gd - the graph div, used to scope the dialog to the plot
15- * @param {string } serverUrl - destination shown in the dialog message
16- * @param {function } onConfirm - called when the user confirms the upload
21+ * @param {string } serverUrl - default destination, pre-filled into the URL input
22+ * @param {function } onConfirm - called with the (possibly edited) server URL when confirmed
1723 */
1824module . exports = function confirmCloudDialog ( gd , serverUrl , onConfirm ) {
1925 var container = d3 . select ( gd . _fullLayout . _paperdiv . node ( ) ) ;
@@ -30,11 +36,34 @@ module.exports = function confirmCloudDialog(gd, serverUrl, onConfirm) {
3036
3137 dialog . append ( 'div' )
3238 . classed ( 'plotly-cloud-dialog-title' , true )
33- . text ( _ ( gd , 'Share with Plotly Cloud ' ) ) ;
39+ . text ( _ ( gd , 'Share Chart ' ) ) ;
3440
35- dialog . append ( 'div' )
41+ var description = dialog . append ( 'div' )
3642 . classed ( 'plotly-cloud-dialog-message' , true )
37- . text ( _ ( gd , 'This chart and its data will be sent to' ) + ' ' + serverUrl + '.' ) ;
43+ . text ( _ ( gd , 'This chart and its data will be sent to' ) + ' ' + serverUrl + '. ' ) ;
44+
45+ // The custom-URL field stays hidden until the user opts in. By default the
46+ // chart is shared to the configured serverUrl; a button in the button row
47+ // reveals this input for anyone who wants to override that destination.
48+ var urlField = dialog . append ( 'div' )
49+ . classed ( 'plotly-cloud-dialog-url-field' , true )
50+ . style ( 'display' , 'none' ) ;
51+
52+ urlField . append ( 'label' )
53+ . classed ( 'plotly-cloud-dialog-label' , true )
54+ . attr ( 'for' , 'plotly-cloud-dialog-url' )
55+ . text ( _ ( gd , 'Dash Enterprise URL' ) ) ;
56+
57+ var input = urlField . append ( 'input' )
58+ . classed ( 'plotly-cloud-dialog-input' , true )
59+ . attr ( 'id' , 'plotly-cloud-dialog-url' )
60+ . attr ( 'type' , 'text' )
61+ . attr ( 'spellcheck' , false )
62+ . attr ( 'placeholder' , 'https://<your-dash-enterprise-instance>/newchart' ) ;
63+
64+ var error = dialog . append ( 'div' )
65+ . classed ( 'plotly-cloud-dialog-error' , true )
66+ . style ( 'display' , 'none' ) ;
3867
3968 var buttons = dialog . append ( 'div' )
4069 . classed ( 'plotly-cloud-dialog-buttons' , true ) ;
@@ -54,6 +83,50 @@ module.exports = function confirmCloudDialog(gd, serverUrl, onConfirm) {
5483 if ( d3 . event . target === overlay . node ( ) ) close ( ) ;
5584 } ) ;
5685
86+ function confirm ( ) {
87+ var url = ( input . property ( 'value' ) || serverUrl ) . trim ( ) ;
88+
89+ if ( ! url ) {
90+ error . text ( _ ( gd , 'Please enter a server URL.' ) ) . style ( 'display' , '' ) ;
91+ input . node ( ) . focus ( ) ;
92+ return ;
93+ }
94+
95+ try {
96+ new URL ( url ) ;
97+ } catch ( e ) {
98+ error . text ( _ ( gd , 'Please enter a valid server URL.' ) ) . style ( 'display' , '' ) ;
99+ input . node ( ) . focus ( ) ;
100+ return ;
101+ }
102+
103+ close ( ) ;
104+ onConfirm ( url ) ;
105+ }
106+
107+ // Hide the error and allow Enter to confirm from the input.
108+ input . on ( 'input' , function ( ) {
109+ error . style ( 'display' , 'none' ) ;
110+ } ) ;
111+ input . on ( 'keydown' , function ( ) {
112+ if ( d3 . event . key === 'Enter' || d3 . event . keyCode === 13 ) confirm ( ) ;
113+ } ) ;
114+
115+ // Sits at the left of the button row, in line with Cancel/Share. Reveals
116+ // the Server URL field and hides itself once a custom URL is requested.
117+ var customBtn = buttons . append ( 'button' )
118+ . classed ( 'plotly-cloud-dialog-btn' , true )
119+ . classed ( 'plotly-cloud-dialog-btn--custom' , true )
120+ . attr ( 'type' , 'button' )
121+ . text ( _ ( gd , 'Share with Dash Enterprise' ) ) ;
122+
123+ customBtn . on ( 'click' , function ( ) {
124+ customBtn . style ( 'display' , 'none' ) ;
125+ urlField . style ( 'display' , '' ) ;
126+ description . text ( _ ( gd , 'This chart and its data will be sent to the server URL you provide.' ) ) ;
127+ input . node ( ) . focus ( ) ;
128+ } ) ;
129+
57130 buttons . append ( 'button' )
58131 . classed ( 'plotly-cloud-dialog-btn' , true )
59132 . classed ( 'plotly-cloud-dialog-btn--cancel' , true )
@@ -64,8 +137,5 @@ module.exports = function confirmCloudDialog(gd, serverUrl, onConfirm) {
64137 . classed ( 'plotly-cloud-dialog-btn' , true )
65138 . classed ( 'plotly-cloud-dialog-btn--confirm' , true )
66139 . text ( _ ( gd , 'Share' ) )
67- . on ( 'click' , function ( ) {
68- close ( ) ;
69- onConfirm ( ) ;
70- } ) ;
140+ . on ( 'click' , confirm ) ;
71141} ;
0 commit comments