""" Indicator modal component for creating and editing indicators. """ from dash import html, dcc def create_indicator_modal(): """Create the indicator modal dialog for adding/editing indicators.""" return html.Div([ dcc.Store(id='edit-indicator-store', data=None), # Store for edit mode - explicitly start with None # Modal Background html.Div( id='indicator-modal-background', style={ 'display': 'none', 'position': 'fixed', 'z-index': '1000', 'left': '0', 'top': '0', 'width': '100%', 'height': '100%', 'background-color': 'rgba(0,0,0,0.5)', 'visibility': 'hidden' } ), # Modal Content html.Div([ html.Div([ # Modal Header html.Div([ html.H4("📊 Add New Indicator", id="modal-title", style={'margin': '0', 'color': '#2c3e50'}), html.Button( "✕", id="close-modal-btn", style={ 'background': 'none', 'border': 'none', 'font-size': '24px', 'cursor': 'pointer', 'color': '#999', 'float': 'right' } ) ], style={'display': 'flex', 'justify-content': 'space-between', 'align-items': 'center', 'margin-bottom': '20px', 'border-bottom': '1px solid #eee', 'padding-bottom': '10px'}), # Modal Body html.Div([ # Basic Settings html.Div([ html.H5("Basic Settings", style={'color': '#2c3e50', 'margin-bottom': '15px'}), # Indicator Name html.Div([ html.Label("Indicator Name:", style={'font-weight': 'bold', 'margin-bottom': '5px'}), dcc.Input( id='indicator-name-input', type='text', placeholder='e.g., "SMA 30 Custom"', style={'width': '100%', 'padding': '8px', 'margin-bottom': '10px', 'border': '1px solid #ddd', 'border-radius': '4px'} ) ]), # Indicator Type html.Div([ html.Label("Indicator Type:", style={'font-weight': 'bold', 'margin-bottom': '5px'}), dcc.Dropdown( id='indicator-type-dropdown', options=[ {'label': 'Simple Moving Average (SMA)', 'value': 'sma'}, {'label': 'Exponential Moving Average (EMA)', 'value': 'ema'}, {'label': 'Relative Strength Index (RSI)', 'value': 'rsi'}, {'label': 'MACD', 'value': 'macd'}, {'label': 'Bollinger Bands', 'value': 'bollinger_bands'} ], placeholder='Select indicator type', style={'margin-bottom': '10px'} ) ]), # Description html.Div([ html.Label("Description (Optional):", style={'font-weight': 'bold', 'margin-bottom': '5px'}), dcc.Textarea( id='indicator-description-input', placeholder='Brief description of this indicator configuration...', style={'width': '100%', 'height': '60px', 'padding': '8px', 'margin-bottom': '15px', 'border': '1px solid #ddd', 'border-radius': '4px', 'resize': 'vertical'} ) ]) ], style={'margin-bottom': '20px'}), # Parameters Section html.Div([ html.H5("Parameters", style={'color': '#2c3e50', 'margin-bottom': '15px'}), # Default message html.Div( id='indicator-parameters-message', children=[html.P("Select an indicator type to configure parameters", style={'color': '#7f8c8d', 'font-style': 'italic'})], style={'display': 'block'} ), # SMA Parameters (hidden by default) html.Div([ html.Label("Period:", style={'font-weight': 'bold', 'margin-bottom': '5px'}), dcc.Input( id='sma-period-input', type='number', value=20, min=1, max=200, style={'width': '100px', 'padding': '8px', 'border': '1px solid #ddd', 'border-radius': '4px'} ), html.P("Number of periods for Simple Moving Average calculation", style={'color': '#7f8c8d', 'font-size': '12px', 'margin-top': '5px'}) ], id='sma-parameters', style={'display': 'none', 'margin-bottom': '10px'}), # EMA Parameters (hidden by default) html.Div([ html.Label("Period:", style={'font-weight': 'bold', 'margin-bottom': '5px'}), dcc.Input( id='ema-period-input', type='number', value=12, min=1, max=200, style={'width': '100px', 'padding': '8px', 'border': '1px solid #ddd', 'border-radius': '4px'} ), html.P("Number of periods for Exponential Moving Average calculation", style={'color': '#7f8c8d', 'font-size': '12px', 'margin-top': '5px'}) ], id='ema-parameters', style={'display': 'none', 'margin-bottom': '10px'}), # RSI Parameters (hidden by default) html.Div([ html.Label("Period:", style={'font-weight': 'bold', 'margin-bottom': '5px'}), dcc.Input( id='rsi-period-input', type='number', value=14, min=2, max=50, style={'width': '100px', 'padding': '8px', 'border': '1px solid #ddd', 'border-radius': '4px'} ), html.P("Number of periods for RSI calculation (typically 14)", style={'color': '#7f8c8d', 'font-size': '12px', 'margin-top': '5px'}) ], id='rsi-parameters', style={'display': 'none', 'margin-bottom': '10px'}), # MACD Parameters (hidden by default) html.Div([ html.Div([ html.Label("Fast Period:", style={'font-weight': 'bold', 'margin-bottom': '5px'}), dcc.Input( id='macd-fast-period-input', type='number', value=12, min=2, max=50, style={'width': '80px', 'padding': '8px', 'border': '1px solid #ddd', 'border-radius': '4px'} ) ], style={'margin-bottom': '10px'}), html.Div([ html.Label("Slow Period:", style={'font-weight': 'bold', 'margin-bottom': '5px'}), dcc.Input( id='macd-slow-period-input', type='number', value=26, min=5, max=100, style={'width': '80px', 'padding': '8px', 'border': '1px solid #ddd', 'border-radius': '4px'} ) ], style={'margin-bottom': '10px'}), html.Div([ html.Label("Signal Period:", style={'font-weight': 'bold', 'margin-bottom': '5px'}), dcc.Input( id='macd-signal-period-input', type='number', value=9, min=2, max=30, style={'width': '80px', 'padding': '8px', 'border': '1px solid #ddd', 'border-radius': '4px'} ) ]), html.P("MACD periods: Fast EMA, Slow EMA, and Signal line", style={'color': '#7f8c8d', 'font-size': '12px', 'margin-top': '5px'}) ], id='macd-parameters', style={'display': 'none', 'margin-bottom': '10px'}), # Bollinger Bands Parameters (hidden by default) html.Div([ html.Div([ html.Label("Period:", style={'font-weight': 'bold', 'margin-bottom': '5px'}), dcc.Input( id='bb-period-input', type='number', value=20, min=5, max=100, style={'width': '80px', 'padding': '8px', 'border': '1px solid #ddd', 'border-radius': '4px'} ) ], style={'margin-bottom': '10px'}), html.Div([ html.Label("Standard Deviation:", style={'font-weight': 'bold', 'margin-bottom': '5px'}), dcc.Input( id='bb-stddev-input', type='number', value=2.0, min=0.5, max=5.0, step=0.1, style={'width': '80px', 'padding': '8px', 'border': '1px solid #ddd', 'border-radius': '4px'} ) ]), html.P("Period for middle line (SMA) and standard deviation multiplier", style={'color': '#7f8c8d', 'font-size': '12px', 'margin-top': '5px'}) ], id='bb-parameters', style={'display': 'none', 'margin-bottom': '10px'}) ], style={'margin-bottom': '20px'}), # Styling Section html.Div([ html.H5("Styling", style={'color': '#2c3e50', 'margin-bottom': '15px'}), html.Div([ # Color Picker html.Div([ html.Label("Color:", style={'font-weight': 'bold', 'margin-bottom': '5px'}), dcc.Input( id='indicator-color-input', type='text', value='#007bff', style={'width': '100px', 'padding': '8px', 'margin-bottom': '10px', 'border': '1px solid #ddd', 'border-radius': '4px'} ) ], style={'width': '48%', 'display': 'inline-block', 'margin-right': '4%'}), # Line Width html.Div([ html.Label("Line Width:", style={'font-weight': 'bold', 'margin-bottom': '5px'}), dcc.Slider( id='indicator-line-width-slider', min=1, max=5, step=1, value=2, marks={i: str(i) for i in range(1, 6)}, tooltip={'placement': 'bottom', 'always_visible': True} ) ], style={'width': '48%', 'display': 'inline-block'}) ]) ], style={'margin-bottom': '20px'}) ]), # Modal Footer html.Div([ html.Button( "Cancel", id="cancel-indicator-btn", style={ 'background-color': '#6c757d', 'color': 'white', 'border': 'none', 'padding': '10px 20px', 'border-radius': '4px', 'cursor': 'pointer', 'margin-right': '10px' } ), html.Button( "Save Indicator", id="save-indicator-btn", style={ 'background-color': '#28a745', 'color': 'white', 'border': 'none', 'padding': '10px 20px', 'border-radius': '4px', 'cursor': 'pointer', 'font-weight': 'bold' } ), html.Div(id='save-indicator-feedback', style={'margin-top': '10px'}) ], style={'display': 'flex', 'justify-content': 'flex-end', 'margin-top': '20px', 'border-top': '1px solid #eee', 'padding-top': '15px'}) ], style={ 'background': 'white', 'padding': '20px', 'border-radius': '8px', 'width': '600px', 'box-shadow': '0 4px 8px rgba(0,0,0,0.1)' }) ], id='indicator-modal-content', style={ 'display': 'none', 'position': 'fixed', 'z-index': '1001', 'left': '0', 'top': '0', 'width': '100%', 'height': '100%', 'visibility': 'hidden' }) ])