got all the indicators working again
This commit is contained in:
parent
b666ec22af
commit
73ed1a092a
|
|
@ -533,6 +533,9 @@ class BrighterTrades:
|
||||||
elif setting == 'edit_indicator':
|
elif setting == 'edit_indicator':
|
||||||
self.indicators.edit_indicator(user_name=user_name, params=params)
|
self.indicators.edit_indicator(user_name=user_name, params=params)
|
||||||
|
|
||||||
|
elif setting == 'delete_indicator':
|
||||||
|
self.indicators.delete_indicator(user_name=user_name, indicator_name=params)
|
||||||
|
|
||||||
elif setting == 'new_indicator':
|
elif setting == 'new_indicator':
|
||||||
self.indicators.new_indicator(user_name=user_name, params=params)
|
self.indicators.new_indicator(user_name=user_name, params=params)
|
||||||
|
|
||||||
|
|
|
||||||
33
src/app.py
33
src/app.py
|
|
@ -155,23 +155,42 @@ def settings():
|
||||||
edit_indicator: Edits the properties of specific indicators.
|
edit_indicator: Edits the properties of specific indicators.
|
||||||
toggle_indicator: Enables or disables display of indicators in the viewport.
|
toggle_indicator: Enables or disables display of indicators in the viewport.
|
||||||
|
|
||||||
:return: None - Redirects to index.
|
:return: None - Redirects to index, or returns JSON for async requests.
|
||||||
"""
|
"""
|
||||||
# Request the user_name from the client session.
|
# Request the user_name from the client session.
|
||||||
if not (user_name := session.get('user')):
|
if not (user_name := session.get('user')):
|
||||||
return redirect('/')
|
return jsonify({"success": False, "message": "Not logged in"}), 401
|
||||||
|
|
||||||
# Return if the user is not logged in.
|
# Return if the user is not logged in.
|
||||||
if not brighter_trades.get_user_info(user_name=user_name, info='Is logged in?'):
|
if not brighter_trades.get_user_info(user_name=user_name, info='Is logged in?'):
|
||||||
return redirect('/')
|
return jsonify({"success": False, "message": "User not logged in"}), 401
|
||||||
|
|
||||||
# Get the setting that the web application wants to change.
|
# Get the setting that the application wants to change.
|
||||||
|
# todo: migrate everything to ajax and clean all this up!!!
|
||||||
|
params = request.form
|
||||||
if not (setting := request.form.get('setting')):
|
if not (setting := request.form.get('setting')):
|
||||||
|
if request.is_json:
|
||||||
|
setting = request.json.get('setting')
|
||||||
|
params = request.json.get('indicator')
|
||||||
|
if not setting:
|
||||||
|
return jsonify({"success": False, "message": "No setting provided"}), 400
|
||||||
|
else:
|
||||||
|
# Redirect if this is a form submission (non-async request)
|
||||||
|
return redirect('/')
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Change the setting.
|
||||||
|
brighter_trades.adjust_setting(user_name=user_name, setting=setting, params=params)
|
||||||
|
|
||||||
|
# Return success as JSON if called via an async request
|
||||||
|
if request.is_json:
|
||||||
|
return jsonify({"success": True}), 200
|
||||||
|
|
||||||
|
# Redirect if this is a form submission (non-async request)
|
||||||
return redirect('/')
|
return redirect('/')
|
||||||
|
|
||||||
# Change the setting.
|
except Exception as e:
|
||||||
brighter_trades.adjust_setting(user_name=user_name, setting=setting, params=request.form)
|
return jsonify({"success": False, "message": str(e)}), 500
|
||||||
return redirect('/')
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/api/history', methods=['POST', 'GET'])
|
@app.route('/api/history', methods=['POST', 'GET'])
|
||||||
|
|
|
||||||
|
|
@ -151,6 +151,14 @@ class ATR(SMA):
|
||||||
|
|
||||||
|
|
||||||
class BolBands(Indicator):
|
class BolBands(Indicator):
|
||||||
|
def __init__(self, name: str, indicator_type: str, properties: dict):
|
||||||
|
super().__init__(name, indicator_type, properties)
|
||||||
|
# Default display properties
|
||||||
|
self.properties.setdefault('period', 20) # The default period for the moving average
|
||||||
|
self.properties.setdefault('devup', 2) # Standard deviation for the upper band
|
||||||
|
self.properties.setdefault('devdn', 2) # Standard deviation for the lower band
|
||||||
|
self.properties.setdefault('ma', 0) # Moving average type (0 = Simple Moving Average in TA-Lib)
|
||||||
|
|
||||||
def calculate(self, candles: pd.DataFrame, user_name: str, num_results: int = 1) -> pd.DataFrame:
|
def calculate(self, candles: pd.DataFrame, user_name: str, num_results: int = 1) -> pd.DataFrame:
|
||||||
"""
|
"""
|
||||||
Calculate the Bollinger Bands indicator for the given candles.
|
Calculate the Bollinger Bands indicator for the given candles.
|
||||||
|
|
@ -177,11 +185,21 @@ class BolBands(Indicator):
|
||||||
'lower': lower
|
'lower': lower
|
||||||
})
|
})
|
||||||
|
|
||||||
|
# Round all values at once
|
||||||
|
df = df.round({'upper': 2, 'middle': 2, 'lower': 2})
|
||||||
|
|
||||||
# Slice the DataFrame to skip initial rows where the indicator might be undefined
|
# Slice the DataFrame to skip initial rows where the indicator might be undefined
|
||||||
return df.iloc[self.properties['period']:]
|
return df.iloc[self.properties['period']:]
|
||||||
|
|
||||||
|
|
||||||
class MACD(Indicator):
|
class MACD(Indicator):
|
||||||
|
def __init__(self, name: str, indicator_type: str, properties: dict):
|
||||||
|
super().__init__(name, indicator_type, properties)
|
||||||
|
# Default display properties
|
||||||
|
self.properties.setdefault('fast_p', 12)
|
||||||
|
self.properties.setdefault('slow_p', 26)
|
||||||
|
self.properties.setdefault('signal_p', 9)
|
||||||
|
|
||||||
def calculate(self, candles: pd.DataFrame, user_name: str, num_results: int = 1) -> pd.DataFrame:
|
def calculate(self, candles: pd.DataFrame, user_name: str, num_results: int = 1) -> pd.DataFrame:
|
||||||
"""
|
"""
|
||||||
Calculate the MACD indicator for the given candles.
|
Calculate the MACD indicator for the given candles.
|
||||||
|
|
@ -207,6 +225,9 @@ class MACD(Indicator):
|
||||||
'hist': hist
|
'hist': hist
|
||||||
})
|
})
|
||||||
|
|
||||||
|
# Replace NaN values with None for JSON compatibility
|
||||||
|
df = df.replace({np.nan: None})
|
||||||
|
|
||||||
# Slice the DataFrame to skip initial rows where the indicator will be undefined
|
# Slice the DataFrame to skip initial rows where the indicator will be undefined
|
||||||
return df.iloc[self.properties['signal_p']:]
|
return df.iloc[self.properties['signal_p']:]
|
||||||
|
|
||||||
|
|
@ -368,11 +389,7 @@ class Indicators:
|
||||||
# attributes.update({'visible': False})
|
# attributes.update({'visible': False})
|
||||||
# # Set the data in indicators according to <attributes>
|
# # Set the data in indicators according to <attributes>
|
||||||
# brighter_trades.indicators.indicator_list[indicator] = attributes
|
# brighter_trades.indicators.indicator_list[indicator] = attributes
|
||||||
#
|
pass
|
||||||
if 'delete' in params:
|
|
||||||
indicator = params['delete']
|
|
||||||
# This will delete in both indicators and config.
|
|
||||||
self.delete_indicator(indicator_name=indicator, user_name=user_name)
|
|
||||||
|
|
||||||
def new_indicator(self, user_name: str, params) -> None:
|
def new_indicator(self, user_name: str, params) -> None:
|
||||||
"""
|
"""
|
||||||
|
|
@ -505,10 +522,16 @@ class Indicators:
|
||||||
"""
|
"""
|
||||||
if not indicator_name:
|
if not indicator_name:
|
||||||
raise ValueError("No indicator name provided.")
|
raise ValueError("No indicator name provided.")
|
||||||
self.users.remove_indicator(indicator_name=indicator_name, user_name=user_name)
|
|
||||||
|
|
||||||
# Force reload from database to refresh cache
|
# Get the user ID to filter the indicators belonging to the user
|
||||||
self.load_indicators(user_name=user_name)
|
user_id = self.users.get_id(user_name)
|
||||||
|
|
||||||
|
# Remove the indicator from the DataFrame where the name matches and the creator is the user
|
||||||
|
self.indicators = self.indicators[
|
||||||
|
~((self.indicators['name'] == indicator_name) & (self.indicators['creator'] == user_id))
|
||||||
|
]
|
||||||
|
|
||||||
|
self.users.remove_indicator(indicator_name=indicator_name, user_name=user_name)
|
||||||
|
|
||||||
def create_indicator(self, creator: str, name: str, kind: str,
|
def create_indicator(self, creator: str, name: str, kind: str,
|
||||||
source: dict, properties: dict, visible: bool = True):
|
source: dict, properties: dict, visible: bool = True):
|
||||||
|
|
|
||||||
|
|
@ -106,6 +106,44 @@ class Comms {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a request to delete an indicator.
|
||||||
|
* @param {string} indicatorName - The name of the indicator to be deleted.
|
||||||
|
* @returns {Promise<Object>} - The response from the server.
|
||||||
|
*/
|
||||||
|
async deleteIndicator(indicatorName) {
|
||||||
|
try {
|
||||||
|
const response = await fetch('/settings', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ setting: 'delete_indicator', indicator: indicatorName })
|
||||||
|
});
|
||||||
|
return await response.json();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error deleting indicator:', error);
|
||||||
|
return { success: false };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a request to update an indicator's properties.
|
||||||
|
* @param {Object} indicatorData - An object containing the updated properties of the indicator.
|
||||||
|
* @returns {Promise<Object>} - The response from the server.
|
||||||
|
*/
|
||||||
|
async updateIndicator(indicatorData) {
|
||||||
|
try {
|
||||||
|
const response = await fetch('/settings', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(indicatorData)
|
||||||
|
});
|
||||||
|
return await response.json();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error updating indicator:', error);
|
||||||
|
return { success: false };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a message to the application server.
|
* Sends a message to the application server.
|
||||||
* @param {string} messageType - The type of the message.
|
* @param {string} messageType - The type of the message.
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,4 @@
|
||||||
|
|
||||||
//
|
|
||||||
//class Header {
|
|
||||||
// constructor() {
|
|
||||||
// this.height = height;
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
class User_Interface{
|
class User_Interface{
|
||||||
/* This contains all the code for our User interface.
|
/* This contains all the code for our User interface.
|
||||||
The code is separated into classes that maintain and
|
The code is separated into classes that maintain and
|
||||||
|
|
@ -45,7 +38,7 @@ class User_Interface{
|
||||||
|
|
||||||
/* Indicators contains methods that interact with indicator
|
/* Indicators contains methods that interact with indicator
|
||||||
related menus and update indicator output in charts and panels. */
|
related menus and update indicator output in charts and panels. */
|
||||||
this.indicators = new Indicators();
|
this.indicators = new Indicators(this.data.comms);
|
||||||
|
|
||||||
/* Register an Indicator callback method to receive updates from the data class. */
|
/* Register an Indicator callback method to receive updates from the data class. */
|
||||||
this.data.registerCallback_i_updates(this.indicators.update);
|
this.data.registerCallback_i_updates(this.indicators.update);
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,15 @@ class Indicator_Output {
|
||||||
}
|
}
|
||||||
this.legend[name].innerHTML = name + ' <span style="color:rgba(4, 111, 232, 1)">' + val + '</span>';
|
this.legend[name].innerHTML = name + ' <span style="color:rgba(4, 111, 232, 1)">' + val + '</span>';
|
||||||
}
|
}
|
||||||
|
clear_legend(name) {
|
||||||
|
// Remove the legend div from the DOM
|
||||||
|
if (this.legend[name]) {
|
||||||
|
this.legend[name].remove(); // Remove the legend from the DOM
|
||||||
|
delete this.legend[name]; // Remove the reference from the object
|
||||||
|
} else {
|
||||||
|
console.warn(`Legend for ${name} not found.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
iOutput = new Indicator_Output();
|
iOutput = new Indicator_Output();
|
||||||
|
|
||||||
|
|
@ -91,9 +100,9 @@ class Indicator {
|
||||||
}
|
}
|
||||||
|
|
||||||
updateDisplay(name, priceValue, value_name) {
|
updateDisplay(name, priceValue, value_name) {
|
||||||
let rounded_value = (Math.round(priceValue * 100) / 100).toFixed(2);
|
// let rounded_value = (Math.round(priceValue * 100) / 100).toFixed(2);
|
||||||
// Update the data in the edit and view indicators panel
|
// // Update the data in the edit and view indicators panel
|
||||||
document.getElementById(this.name + '_' + value_name).value = rounded_value;
|
// document.getElementById(this.name + '_' + value_name).value = rounded_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
setHist(name, data) {
|
setHist(name, data) {
|
||||||
|
|
@ -112,6 +121,37 @@ class Indicator {
|
||||||
updateHist(name, data) {
|
updateHist(name, data) {
|
||||||
this.hist[name].update(data);
|
this.hist[name].update(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
removeFromChart(chart) {
|
||||||
|
// Ensure the chart object is passed
|
||||||
|
if (!chart) {
|
||||||
|
console.error("Chart object is missing.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove all line series associated with this indicator
|
||||||
|
for (let lineName in this.lines) {
|
||||||
|
if (this.lines[lineName]) {
|
||||||
|
chart.removeSeries(this.lines[lineName]);
|
||||||
|
delete this.lines[lineName];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove all histogram series associated with this indicator
|
||||||
|
for (let histName in this.hist) {
|
||||||
|
if (this.hist[histName]) {
|
||||||
|
chart.removeSeries(this.hist[histName]);
|
||||||
|
delete this.hist[histName];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the legend from the crosshair (if any)
|
||||||
|
if (iOutput.legend[this.name]) {
|
||||||
|
iOutput.legend[this.name].remove();
|
||||||
|
delete iOutput.legend[this.name];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class SMA extends Indicator {
|
class SMA extends Indicator {
|
||||||
|
|
@ -142,7 +182,7 @@ indicatorMap.set("SMA", SMA);
|
||||||
class Linear_Regression extends SMA {
|
class Linear_Regression extends SMA {
|
||||||
// Inherits getIndicatorConfig from SMA
|
// Inherits getIndicatorConfig from SMA
|
||||||
}
|
}
|
||||||
indicatorMap.set("Linear_Regression", Linear_Regression);
|
indicatorMap.set("LREG", Linear_Regression);
|
||||||
|
|
||||||
class EMA extends SMA {
|
class EMA extends SMA {
|
||||||
// Inherits getIndicatorConfig from SMA
|
// Inherits getIndicatorConfig from SMA
|
||||||
|
|
@ -197,15 +237,41 @@ class MACD extends Indicator {
|
||||||
}
|
}
|
||||||
|
|
||||||
init(data) {
|
init(data) {
|
||||||
this.setLine('line_m', data[0], 'macd');
|
// Filter out rows where macd, signal, or hist are null
|
||||||
this.setLine('line_s', data[1], 'signal');
|
const filteredData = data.filter(row => row.macd !== null && row.signal !== null && row.hist !== null);
|
||||||
this.setHist(name, data[2]);
|
|
||||||
|
if (filteredData.length > 0) {
|
||||||
|
// Set the 'line_m' for the MACD line
|
||||||
|
this.setLine('line_m', filteredData.map(row => ({
|
||||||
|
time: row.time,
|
||||||
|
value: row.macd
|
||||||
|
})), 'macd');
|
||||||
|
|
||||||
|
// Set the 'line_s' for the signal line
|
||||||
|
this.setLine('line_s', filteredData.map(row => ({
|
||||||
|
time: row.time,
|
||||||
|
value: row.signal
|
||||||
|
})), 'signal');
|
||||||
|
|
||||||
|
// Set the histogram
|
||||||
|
this.setHist('hist', filteredData.map(row => ({
|
||||||
|
time: row.time,
|
||||||
|
value: row.hist
|
||||||
|
})));
|
||||||
|
} else {
|
||||||
|
console.error('No valid MACD data found.');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
update(data) {
|
update(data) {
|
||||||
this.updateLine('line_m', data[0][0], 'macd');
|
// Update the 'macd' line
|
||||||
this.updateLine('line_s', data[1][0], 'signal');
|
this.updateLine('line_m', {time: data[0].time, value: data[0].macd }, 'macd');
|
||||||
this.updateHist(name, data[2][0]);
|
|
||||||
|
// Update the 'signal' line
|
||||||
|
this.updateLine('line_s', { time: data[0].time, value: data[0].signal }, 'signal');
|
||||||
|
|
||||||
|
// Update the 'hist' (histogram) bar
|
||||||
|
this.updateHist('hist', {time: data[0].time, value: data[0].hist });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
indicatorMap.set("MACD", MACD);
|
indicatorMap.set("MACD", MACD);
|
||||||
|
|
@ -264,11 +330,25 @@ class Bolenger extends Indicator {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
init(data) {
|
init(data) {
|
||||||
this.setLine('line_u', data[0], 'value');
|
// Set the 'line_u' for the upper line
|
||||||
this.setLine('line_m', data[1], 'value2');
|
this.setLine('line_u', data.map(row => ({
|
||||||
this.setLine('line_l', data[2], 'value3');
|
time: row.time,
|
||||||
}
|
value: row.upper
|
||||||
|
})), 'value');
|
||||||
|
|
||||||
|
// Set the 'line_m' for the middle line
|
||||||
|
this.setLine('line_m', data.map(row => ({
|
||||||
|
time: row.time,
|
||||||
|
value: row.middle
|
||||||
|
})), 'value2');
|
||||||
|
|
||||||
|
// Set the 'line_l' for the lower line
|
||||||
|
this.setLine('line_l', data.map(row => ({
|
||||||
|
time: row.time,
|
||||||
|
value: row.lower
|
||||||
|
})), 'value3');
|
||||||
|
}
|
||||||
|
|
||||||
update(data) {
|
update(data) {
|
||||||
this.updateLine('line_u', data[0][0], 'value');
|
this.updateLine('line_u', data[0][0], 'value');
|
||||||
|
|
@ -276,12 +356,13 @@ class Bolenger extends Indicator {
|
||||||
this.updateLine('line_l', data[2][0], 'value3');
|
this.updateLine('line_l', data[2][0], 'value3');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
indicatorMap.set("Bolenger", Bolenger);
|
indicatorMap.set("BOLBands", Bolenger);
|
||||||
|
|
||||||
class Indicators {
|
class Indicators {
|
||||||
constructor() {
|
constructor(comms) {
|
||||||
// Contains instantiated indicators.
|
// Contains instantiated indicators.
|
||||||
this.i_objs = {};
|
this.i_objs = {};
|
||||||
|
this.comms = comms;
|
||||||
}
|
}
|
||||||
|
|
||||||
create_indicators(indicators, charts, bt_data) {
|
create_indicators(indicators, charts, bt_data) {
|
||||||
|
|
@ -333,12 +414,68 @@ class Indicators {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This updates all the indicator data
|
||||||
update(updates){
|
update(updates){
|
||||||
for (name in updates){
|
for (name in updates){
|
||||||
window.UI.indicators.i_objs[name].update(updates[name]);
|
window.UI.indicators.i_objs[name].update(updates[name]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deleteIndicator(indicator, event) {
|
||||||
|
this.comms.deleteIndicator(indicator).then(response => {
|
||||||
|
if (response.success) {
|
||||||
|
const indicatorElement = event.target.closest('.indicator-row');
|
||||||
|
indicatorElement.remove(); // Remove from DOM
|
||||||
|
|
||||||
|
// Remove the indicator from the chart and legend
|
||||||
|
if (this.i_objs[indicator]) {
|
||||||
|
let chart;
|
||||||
|
|
||||||
|
// Determine which chart the indicator is on, based on its type
|
||||||
|
if (indicator.includes('RSI')) {
|
||||||
|
chart = window.UI.charts.chart2; // Assume RSI is on chart2
|
||||||
|
} else if (indicator.includes('MACD')) {
|
||||||
|
chart = window.UI.charts.chart3; // Assume MACD is on chart3
|
||||||
|
} else {
|
||||||
|
chart = window.UI.charts.chart_1; // Default to the main chart
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pass the correct chart object when removing the indicator
|
||||||
|
this.i_objs[indicator].removeFromChart(chart);
|
||||||
|
|
||||||
|
// Remove the indicator object from i_objs
|
||||||
|
delete this.i_objs[indicator];
|
||||||
|
|
||||||
|
// Optionally: Clear the legend entry
|
||||||
|
iOutput.clear_legend(indicator);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
alert('Failed to delete the indicator.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// This updates a specific indicator
|
||||||
|
updateIndicator(event) {
|
||||||
|
const row = event.target.closest('.indicator-row');
|
||||||
|
const inputs = row.querySelectorAll('input, select');
|
||||||
|
|
||||||
|
// Gather input data
|
||||||
|
const formObj = {};
|
||||||
|
inputs.forEach(input => {
|
||||||
|
formObj[input.name] = input.type === 'checkbox' ? input.checked : input.value;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.comms.updateIndicator(formObj).then(response => {
|
||||||
|
if (response.success) {
|
||||||
|
alert('Indicator updated successfully.');
|
||||||
|
} else {
|
||||||
|
alert('Failed to update the indicator.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
add_to_list(){
|
add_to_list(){
|
||||||
// Adds user input to a list and displays it in a HTML element.
|
// Adds user input to a list and displays it in a HTML element.
|
||||||
// Used in the Create indicator panel (!)Called from inline html.
|
// Used in the Create indicator panel (!)Called from inline html.
|
||||||
|
|
@ -365,6 +502,7 @@ class Indicators {
|
||||||
}else{
|
}else{
|
||||||
document.getElementById("new_prop_list").insertAdjacentHTML('beforeend', ',' + JSON.stringify(p)); }
|
document.getElementById("new_prop_list").insertAdjacentHTML('beforeend', ',' + JSON.stringify(p)); }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call to display Create new signal dialog.
|
// Call to display Create new signal dialog.
|
||||||
open_form() {
|
open_form() {
|
||||||
// Show the form
|
// Show the form
|
||||||
|
|
|
||||||
|
|
@ -1,80 +1,69 @@
|
||||||
<div class="content" id="indicator_panel" style="max-height: 70px;">
|
<div class="content" id="indicator_panel" style="max-height: 70px;">
|
||||||
<!-- Edit Indicator Panel -->
|
<!-- Edit Indicator Panel -->
|
||||||
|
|
||||||
<div id="edit_indcr_panel" style="display: grid; grid-template-columns: 1fr 1fr;">
|
<div id="edit_indcr_panel" style="display: grid; grid-template-columns: 1fr 1fr;">
|
||||||
<div class="section" style="grid-column: 1;">
|
<div class="section" style="grid-column: 1;">
|
||||||
<button class="btn" onclick="UI.indicators.open_form()" >New Indicator</button>
|
<button class="btn" onclick="UI.indicators.open_form()">New Indicator</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" style="grid-column: 2;">
|
<div class="section" style="grid-column: 2;">
|
||||||
<button class="btn">Indicator Options</button>
|
<button class="btn">Indicator Options</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" style="display: grid; grid-row: 2; grid-column: 1 / span 2; grid-template-columns: 75px 200px 200px auto; overflow-x: scroll;">
|
<div class="section" style="display: grid; grid-row: 2; grid-column: 1 / span 2; grid-template-columns: 75px 200px 200px auto; overflow-x: scroll;">
|
||||||
<h3 style="grid-column: 1 / span 2; text-align: left;">Indicators</h3>
|
<h3 style="grid-column: 1 / span 2; text-align: left;">Indicators</h3>
|
||||||
<hr style="width: 100%; grid-column: 1 / span 10;">
|
<hr style="width: 100%; grid-column: 1 / span 10;">
|
||||||
<div style="grid-column: 2;">
|
<div style="grid-column: 2;">
|
||||||
<h3>Name</h3>
|
<h3>Name</h3>
|
||||||
</div>
|
|
||||||
<div style="grid-column: 3;">
|
|
||||||
<h3>Type</h3>
|
|
||||||
</div>
|
|
||||||
<div style="grid-column: 4 / span 8;">
|
|
||||||
<h3>Properties</h3>
|
|
||||||
</div>
|
|
||||||
<!-- Edit Indicator Rows of individual forms to edit each indicator --!>
|
|
||||||
{% for indicator in indicator_list %}
|
|
||||||
<form action="/settings" method="post" style="display: grid; grid-column: 1 / span 10; grid-template-columns: 75px 200px 200px repeat(7, 1fr);">
|
|
||||||
<input type="hidden" name="setting" value="edit_indicator"/>
|
|
||||||
<div id="edit_indctr_controls" style="grid-column: 1;">
|
|
||||||
<button type="submit" name="delete" class="e_btn" value="{{indicator}}">✘</button>
|
|
||||||
<button type="submit" name="submit" style ="color:darkgreen;" class="e_btn" value="{{indicator}}">✔</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div style="grid-column: 3;">
|
||||||
|
<h3>Type</h3>
|
||||||
|
</div>
|
||||||
|
<div style="grid-column: 4 / span 8;">
|
||||||
|
<h3>Properties</h3>
|
||||||
|
</div>
|
||||||
|
<!-- Edit Indicator Rows without form -->
|
||||||
|
{% for indicator in indicator_list %}
|
||||||
|
<div class="indicator-row" style="display: grid; grid-column: 1 / span 10; grid-template-columns: 75px 200px 200px repeat(7, 1fr);">
|
||||||
|
<input type="hidden" name="setting" value="edit_indicator" />
|
||||||
|
<div id="edit_indctr_controls" style="grid-column: 1;">
|
||||||
|
<button type="button" class="e_btn" onclick="UI.indicators.deleteIndicator('{{indicator}}', event)">✘</button>
|
||||||
|
<button type="button" class="e_btn" style="color:darkgreen;" onclick="UI.indicators.updateIndicator(event)">✔</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="iename" style="grid-column: 2;">{{indicator}}</div>
|
<div class="iename" style="grid-column: 2;">{{indicator}}</div>
|
||||||
|
|
||||||
{% for property in indicator_list[indicator] %}
|
{% for property in indicator_list[indicator] %}
|
||||||
{% set list1 = property.split('_') %}
|
{% set list1 = property.split('_') %}
|
||||||
<div class="ieprop" >
|
<div class="ieprop">
|
||||||
<label class="ietextbox" for="{{indicator}}_{{property}}">{{property}}</label>
|
<label class="ietextbox" for="{{indicator}}_{{property}}">{{property}}</label>
|
||||||
{% if property=='type' %}
|
{% if property=='type' %}
|
||||||
<select class="ietextbox" id="{{indicator}}_{{property}}" name="{{property}}">
|
<select class="ietextbox" id="{{indicator}}_{{property}}" name="{{property}}">
|
||||||
{% for i_type in indicator_types %}
|
{% for i_type in indicator_types %}
|
||||||
<option value="{{i_type}}" {% if indicator_list[indicator][property] == i_type %} selected="selected"{%endif%}>{{i_type}}</option>
|
<option value="{{i_type}}" {% if indicator_list[indicator][property] == i_type %} selected="selected"{%endif%}>{{i_type}}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
{% elif property=='ma' %}
|
{% elif property=='ma' %}
|
||||||
<select class="ietextbox" id="{{indicator}}_{{property}}" name="{{property}}">
|
<select class="ietextbox" id="{{indicator}}_{{property}}" name="{{property}}">
|
||||||
{% for ma_val in ma_vals %}
|
{% for ma_val in ma_vals %}
|
||||||
<option value="{{ma_vals[ma_val]}}" {% if indicator_list[indicator][property] == ma_vals[ma_val] %} selected="selected"{%endif%}>{{ma_val}}</option>
|
<option value="{{ma_vals[ma_val]}}" {% if indicator_list[indicator][property] == ma_vals[ma_val] %} selected="selected"{%endif%}>{{ma_val}}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
{% elif property=='color' or list1[0]=='color' %}
|
{% elif property=='color' or list1[0]=='color' %}
|
||||||
<input class="ietextbox" type="color" id="{{indicator}}_{{property}}"
|
<input class="ietextbox" type="color" id="{{indicator}}_{{property}}" value="{{indicator_list[indicator][property]}}" name="{{property}}">
|
||||||
value="{{indicator_list[indicator][property]}}"
|
|
||||||
name="{{property}}">
|
|
||||||
{% elif property=='period' %}
|
{% elif property=='period' %}
|
||||||
<input class="ietextbox" type="number" id="{{indicator}}_{{property}}"
|
<input class="ietextbox" type="number" id="{{indicator}}_{{property}}" value="{{indicator_list[indicator][property]}}" name="{{property}}">
|
||||||
value="{{indicator_list[indicator][property]}}"
|
|
||||||
name="{{property}}">
|
|
||||||
{% elif property=='visible' %}
|
{% elif property=='visible' %}
|
||||||
<input class="ietextbox" type="checkbox" id="{{indicator}}_{{property}}"
|
<input class="ietextbox" type="checkbox" id="{{indicator}}_{{property}}" value="{{indicator_list[indicator][property]}}" name="{{property}}" {% if indicator in checked %} checked {%endif%}>
|
||||||
value="{{indicator_list[indicator][property]}}"
|
|
||||||
name="{{property}}"
|
|
||||||
{% if indicator in checked %} checked{%endif%}>
|
|
||||||
{% elif property=='value' %}
|
{% elif property=='value' %}
|
||||||
<input class="ie_value" type="number" id="{{indicator}}_{{property}}"
|
<input class="ie_value" type="number" id="{{indicator}}_{{property}}" value="{{indicator_list[indicator][property]}}" name="{{property}}" readonly>
|
||||||
value="{{indicator_list[indicator][property]}}"
|
|
||||||
name="{{property}}" readonly>
|
|
||||||
{% else %}
|
{% else %}
|
||||||
<input class="ietextbox" type="text" id="{{indicator}}_{{property}}"
|
<input class="ietextbox" type="text" id="{{indicator}}_{{property}}" value="{{indicator_list[indicator][property]}}" name="{{property}}">
|
||||||
value="{{indicator_list[indicator][property]}}"
|
{% endif %}
|
||||||
name="{{property}}">
|
</div>
|
||||||
{%endif%}
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
</form>
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<!-- End of Rows of individual forms to edit each indicator --!>
|
</div>
|
||||||
</div>
|
{% endfor %}
|
||||||
</div>
|
<!-- End of Rows for each indicator -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue