diff --git a/my_flask_app/__pycache__/main.cpython-39.pyc b/my_flask_app/__pycache__/main.cpython-39.pyc index 068245242330937a344b5e4907b246345019b383..0f6447fa55eaa8f10df992e71e8b5cd526f6f6d1 100644 Binary files a/my_flask_app/__pycache__/main.cpython-39.pyc and b/my_flask_app/__pycache__/main.cpython-39.pyc differ diff --git a/my_flask_app/main.py b/my_flask_app/main.py index b7d9e78e4353b12bb7b390bb2047f2fb074d5c68..36e5cf9c442d5675312204c44df7402a1f94dd8b 100644 --- a/my_flask_app/main.py +++ b/my_flask_app/main.py @@ -94,7 +94,7 @@ def index(): print("111") for name in dropped_items: print(name) - if dropped_items==[]: + if dropped_items == []: image2 = "" else: tables2 = importMetadata(engine, None, dropped_items, False) @@ -103,7 +103,7 @@ def index(): print("222") - extract_ME_table(engine, 'event_data', 'E', 'time', ['col', 'machine_id'], [' col ', ' name ', ' Z_ACTUAL_ZERO_POINT '], ['value(fine, coarse)'], datetime(2022, 11, 1, 17, 5), datetime(2022, 11, 3, 0, 0)) + # extract_ME_table(engine, 'event_data', 'E', 'time', ['col', 'machine_id'], [' col ', ' name ', ' Z_ACTUAL_ZERO_POINT '], ['value(fine, coarse)'], datetime(2022, 11, 1, 17, 5), datetime(2022, 11, 3, 0, 0)) return render_template('app.html', database=database, schemas=schemas, show_all=show_all, schema_Selected=schema_Selected, tables=tables1, image1=image1, image2=image2, dropped_items=dropped_items, self_labels=self_labels) @@ -138,7 +138,7 @@ def handle_drop(): item_name = data.get('item') action = data.get('action') - dropped_items = session.get('target_table_names', '') + dropped_items = session.get('target_table_names', []) print("444") if action == 'added': dropped_items.append(item_name) @@ -155,6 +155,25 @@ def handle_drop(): return jsonify(image2=image2) +@app.route('/reset-target-table', methods=['POST']) +def reset_target_table(): + print("reset") + database_uri = session.get('db_uri', '') + engine = create_engine(database_uri) + session['target_table_names'] = [] + schema_Selected = session.get('schema_selected', None) + show_all = session.get('show_all', False) + + # Regenerate ERD based on the updated dropped_items + themes = getThemes() + tables1 = importMetadata(engine, schema_Selected, None, show_all) + tables2 = importMetadata(engine, None, [], False) + graph_DOT2 = createGraph([], themes["Blue Navy"], True, True, True) + image2 = generate_erd(graph_DOT2) + + tables1 = [table for table in tables1] # Ensure CustomTable has a to_dict method + + return jsonify(image2=image2, tables=tables1) @app.route('/get-table-data', methods=['POST']) def get_table_data(): @@ -454,6 +473,7 @@ def check_json_column(engine, table_name) -> list: def handle_json_column(engine, table_name, column_name): insp = inspect(engine) + isSQLite = insp.dialect.name == 'sqlite' # Create a connection from the engine with engine.connect() as conn: @@ -470,11 +490,17 @@ def handle_json_column(engine, table_name, column_name): conn.close() jsonKeys = [] - for row in result: # row is a tuple, row[0] is a dictionary - # print(row[0]) - name = tuple(sorted(row[0].keys()))if type(row[0]) == dict else json.loads(row[0]).keys() + for row in result: # row is a tuple, row[0] is a dictionary + # Convert the keys to a sorted tuple for consistency + if type(row[0]) == dict: + name = tuple(sorted(row[0].keys())) + else: + name = tuple(sorted(json.loads(row[0]).keys())) + + # Append the key list if it's not already in jsonKeys if name not in jsonKeys: jsonKeys.append(name) + print(jsonKeys) return jsonKeys @@ -606,7 +632,7 @@ def getObjectColumns(table_name:str) -> list: return object_columns -def query_database_for_table_content(engine, table_name, number=100): +def query_database_for_table_content(engine, table_name, number=200): # Initialize content list content_list = [] # Create a connection from the engine @@ -701,9 +727,10 @@ def get_min_max_datetime(engine, table_name, time_column, start_time=None, end_t return None, None - def extract_ME_table(engine, table_name: str, type: str, time_column: str, object: list, label: list, features_name: list, start_time: datetime = None, end_time: datetime = None) -> list: conn = engine.connect() + insp = inspect(engine) + database_name = insp.dialect.name # 'postgresql' or 'sqlite' table_instance = getTableInstance(engine, table_name) label_column = label[1].strip() label_value = label[2].strip() @@ -737,7 +764,10 @@ def extract_ME_table(engine, table_name: str, type: str, time_column: str, objec column_name, keys = feature[:-1].split('(') keys = keys.split(', ') for key in keys: - json_extraction = f"{full_table_name}.{column_name}->>'{key}' AS {key}" + if database_name == 'postgresql': + json_extraction = f"{full_table_name}.{column_name}->>'{key}' AS {key}" + elif database_name == 'sqlite': + json_extraction = f"json_extract({full_table_name}.{column_name}, '$.{key}') AS {key}" json_extractions.append(json_extraction) else: sql_columns.append(f"{full_table_name}.{feature}") diff --git a/my_flask_app/templates/app.html b/my_flask_app/templates/app.html index 2583177162201e466188aa4cd0d036b20e109d33..f8e43df24b8acb232936589e2520ef1094a7c523 100644 --- a/my_flask_app/templates/app.html +++ b/my_flask_app/templates/app.html @@ -42,7 +42,7 @@ background-color: #add8e6; padding: 10px; margin: 0; - margin-top: -1px; + margin-top: 0px; box-sizing: border-box; position: fixed; /* Fixed positioning */ @@ -195,6 +195,7 @@ justify-content: space-between; align-items: center; margin-top: -4vh; + text-align: center; } .terminal-body { padding: 1rem; @@ -407,20 +408,17 @@ <legend style="margin-top: 3px;">Target Tables:</legend> <div class="border border-secondary rounded" id="table_list" > - <div id="dropped_items"> - <div uk-sortable="group: sortable-group" class="uk-list uk-list-collapse "> - {% for item in dropped_items %} - <div class="uk-margin" style="height: 15px; margin-bottom: -4px;"> - <div class="list-group-item-action uk-card uk-card-default uk-card-body uk-card-small" style="height: 15px; padding-top: 5px;">{{ item }}</div> - </div> - {% endfor %} - </div> + <div id="dropped_items" uk-sortable="group: sortable-group" class="uk-list uk-list-collapse "> + <!-- <div > --> + {% for item in dropped_items %} + <div class="uk-margin" style="height: 15px; margin-bottom: -4px;"> + <div class="list-group-item-action uk-card uk-card-default uk-card-body uk-card-small" style="height: 15px; padding-top: 5px;">{{ item }}</div> + </div> + {% endfor %} + <!-- </div> --> </div> </div> - <!-- don't use form, try use javascript to handle the reset button --> - <form action="/handle-drop" method="POST"> - <button id="resetButton" type="submit" class="btn btn-secondary headerButton">Reset</button> - </form> + <button id="resetButton" class="btn btn-secondary headerButton">Reset</button> </div> <div id="content"> @@ -654,10 +652,8 @@ <div class="custom-buttom-bar"> <div id="terminal" class="terminal"> <div id="terminal-header" class="terminal-header"> - <span style="position: absolute; left: 5px;">Table</span> <span uk-icon="menu" style="position: absolute; right: 70vh;"></span> - <!-- <span id="close-terminal" uk-icon="close" style="position: absolute; right: 1vh; z-index: 1000;"></span> --> - <button type="button" class="btn-close" aria-label="Close" data-bs-dismiss="modal" style="position: absolute; right: 1vh; margin-top: 1px; z-index: 1000;" onclick="toggleTerminal()"></button> - <!-- <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> --> + <span style="position: absolute; left: 5px; margin-top: 7px">Table</span><span aria-hidden="true" uk-icon="menu" style="margin-top: 4px;"></span> + <button id="myModal" type="button" class="btn-close" aria-label="Close" data-bs-dismiss="modal" style="position: absolute; right: 1vh; margin-top: 1px; z-index: 1000;" onclick="closeTerminal()"></button> </div> <div id=terminal-body class="terminal-body"> <p> No table selected.</p> @@ -707,7 +703,7 @@ <div id="resize-handle-left" class="resize-handle-left"></div> </div> - +<!-----------------------------------------------------------------------------------------------------> <script> var jq = jQuery.noConflict(); function initializeSlider(minDatetime, maxDatetime) { @@ -748,7 +744,6 @@ } // Initialize the slider with dynamic datetime values - console.log("initialize slider with dynamic datetime values"); jq("#slider-range").slider({ range: true, min: toTimestamp(minDatetime), // Use minDatetime from the server @@ -763,6 +758,13 @@ var endDateTime = new Date(ui.values[1]); jq("#amount1").val(formatDateTime(startDateTime)); jq("#amount2").val(formatDateTime(endDateTime)); + }, + create: function(event, ui) { + // Set the initial datetime values when the slider is created + var startDateTime = new Date(jq("#slider-range").slider("values", 0)); + var endDateTime = new Date(jq("#slider-range").slider("values", 1)); + jq("#amount1").val(formatDateTime(startDateTime)); + jq("#amount2").val(formatDateTime(endDateTime)); } }); } @@ -803,7 +805,6 @@ } - function click_all_MD_table(element) { var checkboxes = document.querySelectorAll('#MD-table tbody input[type="checkbox"]'); checkboxes.forEach(function(checkbox) { @@ -1272,9 +1273,9 @@ } - function closeTerminal() { + function closeTerminal() { var terminal = document.getElementById('terminal'); - terminal.style.height = `0 px`; + terminal.style.height = '0px'; // Correctly set height to 0px without space } @@ -1494,6 +1495,39 @@ } } + document.getElementById('resetButton').addEventListener('click', function() { + // event.preventDefault(); // Prevent the default form submission + console.log('Reset button clicked'); + // Send a POST request to the server + fetch('/reset-target-table', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + } + }) + .then(response => response.json()) + .then(data => { + document.getElementById('show_tables1').innerHTML = ''; + document.getElementById('dropped_items').innerHTML =''; // Clear the dropped items + for (let i = 0; i < data.tables.length; i++) { + var item1 = document.createElement('div'); + item1.className = "list-group-item-action uk-card uk-card-default uk-card-body uk-card-small"; + item1.style = "height: 15px; padding-top: 5px;"; + item1.textContent = data.tables[i]; + var item2 = document.createElement('div'); + item2.className = "uk-margin"; + item2.style = "height: 15px; margin-bottom: -4px;"; + item2.appendChild(item1); + document.getElementById('show_tables1').appendChild(item2); + } + + showErdCanvas("erdCanvas2", "zoomInBtn2", "zoomOutBtn2", data.image2); + showErdCanvas("erdCanvas3", "zoomInBtn3", "zoomOutBtn3", data.image2); + + }) + .catch(error => console.error('Error:', error)); + }); + document.querySelectorAll('.type-radio').forEach(function(radio) { radio.addEventListener('change', function() { @@ -1587,10 +1621,7 @@ }); - document.getElementById('close-terminal').addEventListener('click', function() { - closeTerminal(); - }); - + // function select_schema(){ @@ -1659,47 +1690,6 @@ // }); // } - - - // document.getElementById('resetButton').addEventListener('click', function(event) { - // event.preventDefault(); // Prevent the default form submission - - // // Send a POST request to the server - // fetch('/handle-drop', { - // method: 'POST', - // body: JSON.stringify({'reset': true}), - // headers: { - // 'Content-Type': 'application/json' - // } - // }) - // .then(response => response.json()) - // .then(data => { - // // let tables_list = data['tables']; - // document.getElementById('tables').innerHTML = data.tables; - // // for (let i = 0; i < tables_list.length; i++) { - // // let table = tables_list[i]; - // // let item_inner = document.createElement('div'); - // // item_inner.className = 'ist-group-item-action uk-card uk-card-default uk-card-body uk-card-small'; - // // item_inner.style = "height: 15px; padding-top: 5px;" - // // item_inner.textContent = table; - - // // let item_outer = document.createElement('div'); - // // item_outer.className = 'uk-margin'; - // // item_outer.style = "height: 15px; margin-bottom: -4px;" - // // item_outer.appendChild(item_inner); - - // // document.getElementById('show_tables1').appendChild(item_outer); - // // } - // document.getElementById('dropped_items').innerHTML =data.dropped_items; - // showErdCanvas("erdCanvas2", "zoomInBtn2", "zoomOutBtn2", data.image2); - // showErdCanvas("erdCanvas3", "zoomInBtn3", "zoomOutBtn3", data.image2); - - // }) - // .catch(error => console.error('Error:', error)); - // }); - - // Attach click event listener to each dropped item - }); </script>