diff --git a/my_flask_app/__pycache__/main.cpython-39.pyc b/my_flask_app/__pycache__/main.cpython-39.pyc index d4b09b0d9746781714fb499d9d6f9e0daa18e49b..197f3a0c6f0b12d1beee27123df9ba4302797d1b 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 4516f28439fc3dab7bface7b8351b81070169c97..5ad81ab1297e18cdcb0039722521c3ef3107b47e 100644 --- a/my_flask_app/main.py +++ b/my_flask_app/main.py @@ -1,6 +1,6 @@ import pandas as pd from my_flask_app import app -from .models.models import CustomTable, CustomColumn, Theme, CompressedDataType, RegType, RegRole +from .models.models import CustomTable, CustomColumn, Theme, CompressedDataType, Observation_Spec, RegType, RegRole from flask_sqlalchemy import SQLAlchemy from flask import jsonify, redirect, render_template, request, session, url_for, json from sqlalchemy import ARRAY, BIGINT, BOOLEAN, DOUBLE_PRECISION, FLOAT, INTEGER, JSON, NUMERIC, SMALLINT, TIMESTAMP, UUID, VARCHAR, MetaData, String, create_engine, text, inspect @@ -49,6 +49,7 @@ def index(): session['self_defined_labels'] = [] session['schema_selected'] = '' session['show_all'] = False + session['data_header']={'event':[], 'measurement':[], 'segment':[], 'segmentData':[]} print("4") # Initialize inspector here, outside the inner if-else print("4.5") @@ -169,7 +170,7 @@ def get_table_data(): table_columns = [column.name for column in table_instance.columns] sorted_table_columns = sorted(table_columns) - + # de-nested the JSON columns from the feature_columns feature_columns = sorted_table_columns if check_json_column(engine, table_name) != []: json_column_names = check_json_column(engine, table_name) @@ -179,8 +180,6 @@ def get_table_data(): for key in jsonKeys: feature_columns.append( column_name + str(key) ) if len(key) > 1 else feature_columns.append( column_name + str(key).replace(',', '')) - - return jsonify({ 'html_table': html_table, 'table_columns': sorted_table_columns, 'feature_columns': feature_columns }) @@ -220,6 +219,34 @@ def add_label(): return jsonify({'defined_labels': self_defined_labels}) +@app.route('/add-data-header', methods=['POST']) +def add_data_header(): + data_header = session.get('data_header', {'event':[], 'measurement':[], 'segment':[], 'segmentData':[]}) + data = request.json + type = data.get('type') if data.get('type') != None else '' + label = data.get('label') if data.get('label') != None else '' + object_column = data.get('object_column') if data.get('object_column') != None else '' + value_list = data.get('value_list') if data.get('value_list') != None else [] + + if type == 'event': + observation = Observation_Spec(type, label, value_list) + data_header['event'].append(observation.to_dict()) + elif type == 'measurement': + observation = Observation_Spec(type, label, value_list) + data_header['measurement'].append(observation.to_dict()) + elif type == 'segment': + observation = Observation_Spec(type, label, value_list) + data_header['segment'].append(observation.to_dict()) + elif type == 'segmentData': + observation = Observation_Spec(type, label, value_list) + data_header['segmentData'].append(observation.to_dict()) + + print("88888") + print(data_header) + session['data_header'] = data_header + + return jsonify({'data_header': data_header}) + def check_json_column(engine, table_name): insp = inspect(engine) schema = getTableSchema(table_name) if insp.dialect.name == 'postgresql' else insp.default_schema_name @@ -233,6 +260,7 @@ def check_json_column(engine, table_name): print(json_column_names) return json_column_names + def handle_json_column(engine, table_name, column_name): insp = inspect(engine) @@ -251,8 +279,9 @@ def handle_json_column(engine, table_name, column_name): conn.close() jsonKeys = [] - for row in result: - name = tuple(sorted(row[0].keys())) + 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() if name not in jsonKeys: jsonKeys.append(name) print(jsonKeys) diff --git a/my_flask_app/models/__pycache__/models.cpython-39.pyc b/my_flask_app/models/__pycache__/models.cpython-39.pyc index 00c03fc284ad7a2156ca2601ed3f7e504a3b2388..c934da4ed83aa67dbcb94493d6d76507c6c13579 100644 Binary files a/my_flask_app/models/__pycache__/models.cpython-39.pyc and b/my_flask_app/models/__pycache__/models.cpython-39.pyc differ diff --git a/my_flask_app/models/models.py b/my_flask_app/models/models.py index 4fe07bf4e5843fe35bcf3e6c17a1e37ac3127e85..f19dfeff392718ba0cb3f7fe50e01a2b2f70d669 100644 --- a/my_flask_app/models/models.py +++ b/my_flask_app/models/models.py @@ -15,6 +15,19 @@ class Observation_Spec: def remove_feature(self, name): self.features_name.remove(name) + def to_dict(self): + return { + 'type': self.type, + 'label': self.label, + 'features_name': self.features_name + } + + @staticmethod + def from_dict(data): + observation_spec = Observation_Spec(data['type'], data['label'], data['features_name']) + + return observation_spec + class Obesrvation(Observation_Spec): def __init__(self, time, type, object, label, features_name:list = None, feature:dict = None): super().__init__(type, label, features_name=None) diff --git a/my_flask_app/templates/app.html b/my_flask_app/templates/app.html index 353e6d59dec7e742581a42dc974b593fd6526839..0d04707fd7ee6f9c22619b10b03f8d00a8363030 100644 --- a/my_flask_app/templates/app.html +++ b/my_flask_app/templates/app.html @@ -25,6 +25,7 @@ <style> body { /* position: fixed; */ + overflow: hidden; display: flex; flex-direction: row; height: 100vh; @@ -115,7 +116,13 @@ padding: 0; border: none; /* Remove border to make it seamless */ } - select, button { width: 80%; } + button { width: 80%; } + .headerButton { + width: 75px; + margin: 5px 0px; + border: none; + background-color: #5ea9e2; + } #canvasContainer { min-height: 84vh; max-height: max-content; @@ -228,8 +235,32 @@ select { width: 100%; } + .headerSelect{ + width: 220px; + } .chosen-container { - width: 100% !important; /* Use !important to override inline styles if necessary */ + width: 450px !important; /* Use !important to override inline styles if necessary */ + } + .chosen-container-multi .chosen-choices{ + border-radius: 6px; + height: 40px !important; + cursor: text; + margin-top: 3px; + border: 1px solid #ddd; + text-indent: 0; + font-size: medium; + + padding: 0.3em; + min-height: 34px; /* Adjust the min-height accordingly */ + overflow-y: auto; + } + .chosen-container-multi .chosen-choices li.search-choice { + line-height: 1.1; + margin: 3px; + border-radius: 3px; + } + .chosen-container .chosen-choices li.search-choice span { + font-size: 14px; /* Adjust font size here */ } /* Removes the Chosen removal button image */ .chosen-container-multi .chosen-choices li.search-choice .search-choice-close { @@ -239,7 +270,14 @@ font-family: "Font Awesome 5 Brands", sans-serif; content: "\f099"; color: red; - font-size: 12px; + font-size: 14px; + } + #scrollable-panel { + flex: 1 1 auto; /* Don't grow, don't shrink, keep the size based on its content */ + width: 50%; /* Adjust as needed */ + max-height: 100vh; + position: sticky; + top: 0; } </style> </head> @@ -253,89 +291,123 @@ <div class="mb-3"> <label for="disabledTextInput" class="form-label" style="margin-top: 10px;">{{database}}.db</label> </div> - <div class="accordion" style="margin-top: 5px;"> - <div class="accordion-item"> - <h2 class="accordion-header"> - <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseOne" aria-expanded="true" aria-controls="collapseOne"> - Schema - </button> - </h2> - <div id="collapseOne" class="accordion-collapse collapse" data-bs-parent="#accordionExample"> - <div class="accordion-body"> - <form method="post"> - <input class="form-check-input" id="showAllClick" style="margin: 2px 2px 2px 5px; border-color: black;" type="checkbox" name="show_all" value="True" onchange="this.form.submit()"> - <!-- <span class="uk-label" style="margin: 1px;" >show all</span> --> - <label class="form-check-label" for="showAllClick" style="margin-top: 3px;"> - Primary Tables - </label> - <select class="form-select" name="schema" id="schemaSelect" onchange="this.form.submit()" style="padding: 0px 1px 2px 1px;"> - <option value="">Choose here</option> - {% for schema in schemas %} - <option value="{{ schema }}" {% if schema == schema_Selected %} selected {% endif %}>{{ schema }}</option> - {% endfor %} - </select> + + <ul uk-accordion> + <li> + <a class="uk-accordion-title" href="#">Database URL</a> + <div class="uk-accordion-content"> + + <form method="post" action="/"> + <div class="mb-3"> + <!-- <label for="exampleInputPassword1" name="database_uri" class="form-label">Database URI</label> --> + <input type="text" class="form-control" id="exampleInputPassword1" name="database_uri" placeholder="Enter Database URI"> + <button type="submit" class="btn btn-primary headerButton"> Submit </button> + </div> </form> - </div> - </div> - </div> - <div class="accordion-item"> - <h2 class="accordion-header"> - <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseTwo" aria-expanded="true" aria-controls="collapseTwo"> - Time - </button> - </h2> - <div id="collapseTwo" class="accordion-collapse collapse" data-bs-parent="#accordionExample"> - <div class="accordion-body"> - <!-- <strong>This is the first item's accordion body.</strong> It is shown by default, until the collapse plugin adds the appropriate classes that we use to style each element. These classes control the overall appearance, as well as the showing and hiding via CSS transitions. You can modify any of this with custom CSS or overriding our default variables. It's also worth noting that just about any HTML can go within the <code>.accordion-body</code>, though the transition does limit overflow. --> - </div> - </div> - </div> - <div class="accordion-item"> - <h2 class="accordion-header"> - <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseThree" aria-expanded="false" aria-controls="collapseThree"> - Object - </button> - </h2> - <div id="collapseThree" class="accordion-collapse collapse" data-bs-parent="#accordionExample"> - <div class="accordion-body"> - <!-- <strong>This is the second item's accordion body.</strong> It is hidden by default, until the collapse plugin adds the appropriate classes that we use to style each element. These classes control the overall appearance, as well as the showing and hiding via CSS transitions. You can modify any of this with custom CSS or overriding our default variables. It's also worth noting that just about any HTML can go within the <code>.accordion-body</code>, though the transition does limit overflow. --> + </div> - </div> - </div> - <div class="accordion-item"> - <h2 class="accordion-header"> - <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseFour" aria-expanded="false" aria-controls="collapseFour"> - Label - </button> - </h2> - <div id="collapseFour" class="accordion-collapse collapse" data-bs-parent="#accordionExample"> - <div class="accordion-body"> - <!-- <strong>This is the third item's accordion body.</strong> It is hidden by default, until the collapse plugin adds the appropriate classes that we use to style each element. These classes control the overall appearance, as well as the showing and hiding via CSS transitions. You can modify any of this with custom CSS or overriding our default variables. It's also worth noting that just about any HTML can go within the <code>.accordion-body</code>, though the transition does limit overflow. --> + </li> + + + <li> + <a class="uk-accordion-title" href="#">Filter</a> + <div class="uk-accordion-content"> + + <div class="accordion"> + <div class="accordion-item"> + <h2 class="accordion-header"> + <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseOne" aria-expanded="true" aria-controls="collapseOne"> + Schema + </button> + </h2> + <div id="collapseOne" class="accordion-collapse collapse" data-bs-parent="#accordionExample"> + <div class="accordion-body"> + <form method="post"> + <input class="form-check-input" id="showAllClick" style="margin: 2px 2px 2px 5px; border-color: black;" type="checkbox" name="show_all" value="True" onchange="this.form.submit()"> + <!-- <span class="uk-label" style="margin: 1px;" >show all</span> --> + <label class="form-check-label" for="showAllClick" style="margin-top: 3px;"> + Primary Tables + </label> + <select class="form-select" name="schema" id="schemaSelect" onchange="this.form.submit()" onclick="openTables()" style="padding: 0px 1px 2px 1px;"> + <option value="">Choose here</option> + {% for schema in schemas %} + <option value="{{ schema }}" {% if schema == schema_Selected %} selected {% endif %}>{{ schema }}</option> + {% endfor %} + </select> + </form> + </div> + </div> + </div> + <div class="accordion-item"> + <h2 class="accordion-header"> + <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseTwo" aria-expanded="true" aria-controls="collapseTwo"> + Time + </button> + </h2> + <div id="collapseTwo" class="accordion-collapse collapse" data-bs-parent="#accordionExample"> + <div class="accordion-body"> + <!-- <strong>This is the first item's accordion body.</strong> It is shown by default, until the collapse plugin adds the appropriate classes that we use to style each element. These classes control the overall appearance, as well as the showing and hiding via CSS transitions. You can modify any of this with custom CSS or overriding our default variables. It's also worth noting that just about any HTML can go within the <code>.accordion-body</code>, though the transition does limit overflow. --> + </div> + </div> + </div> + <div class="accordion-item"> + <h2 class="accordion-header"> + <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseThree" aria-expanded="false" aria-controls="collapseThree"> + Object + </button> + </h2> + <div id="collapseThree" class="accordion-collapse collapse" data-bs-parent="#accordionExample"> + <div class="accordion-body"> + <!-- <strong>This is the second item's accordion body.</strong> It is hidden by default, until the collapse plugin adds the appropriate classes that we use to style each element. These classes control the overall appearance, as well as the showing and hiding via CSS transitions. You can modify any of this with custom CSS or overriding our default variables. It's also worth noting that just about any HTML can go within the <code>.accordion-body</code>, though the transition does limit overflow. --> + </div> + </div> + </div> + <div class="accordion-item"> + <h2 class="accordion-header"> + <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseFour" aria-expanded="false" aria-controls="collapseFour"> + Label + </button> + </h2> + <div id="collapseFour" class="accordion-collapse collapse" data-bs-parent="#accordionExample"> + <div class="accordion-body"> + <!-- <strong>This is the third item's accordion body.</strong> It is hidden by default, until the collapse plugin adds the appropriate classes that we use to style each element. These classes control the overall appearance, as well as the showing and hiding via CSS transitions. You can modify any of this with custom CSS or overriding our default variables. It's also worth noting that just about any HTML can go within the <code>.accordion-body</code>, though the transition does limit overflow. --> + </div> + </div> + </div> + </div> + </div> - </div> - </div> - </div> - - <h4 style="margin-top: 0px;">Tables:</h4> - <div class="border border-secondary rounded" id="table_list" style="margin-bottom: 5px; margin-top: -10px;"> - <div id="table_list_source"> - <div id="show_tables1" uk-sortable="group: sortable-group" class="uk-list uk-list-collapse"> - {% for table in tables %} - <div id="show_tables2" 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;">{{ table }}</div> + </li> + + + <li class="uk-class"> + <a class="uk-accordion-title" href="#">Tables</a> + <div class="uk-accordion-content"> + + <div class="border border-secondary rounded" id="table_list" style="margin-bottom: 5px; margin-top: -10px;"> + <div id="table_list_source"> + <div id="show_tables1" uk-sortable="group: sortable-group" class="uk-list uk-list-collapse"> + {% for table in tables %} + <div id="show_tables2" 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;">{{ table }}</div> + </div> + {% endfor %} + </div> </div> - {% endfor %} + </div> + </div> - </div> - </div> + </li> + </ul> + - <h4 style="margin-top: -4px;">Target Tables:</h4> + <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" onclick="showOptions(this)" style="height: 15px; padding-top: 5px;">{{ item }}</div> + <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> @@ -343,24 +415,25 @@ </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 btn-sm">Reset</button> + <button id="resetButton" type="submit" class="btn btn-secondary headerButton">Reset</button> </form> </div> <div id="content"> <button class="uk-button uk-button-default uk-button-small custom-push-button" type="button" uk-toggle="target: #sidebar1" onclick="toggleSidebar()"></button> <ul uk-tab class="uk-flex-center" data-uk-tab="{connect:'#my-id'}" style="margin-top: 10px; z-index: 0;"> - <li><a href="#">ERD</a></li> - <li><a href="#">Other Content</a></li> + <li><a href="#">ERD</a></li> + <li><a href="#">Create Data Header</a></li> + <li><a href="#">Create Data instance</a></li> </ul> <!-- <div> --> <ul id="my-id" class="uk-switcher"> <li><a href="#" id="autoplayer" data-uk-switcher-item="next"></a> - <div style="display: flex; flex-direction: row; height: 85vh;"> + <div style="display: flex; flex-direction: row; height: 85vh; border: 0px 1px;"> <div style="flex: 0,3; display: flex; flex-direction: column;"> - <h4>Filtered ERD</h4> + <h4 style="margin: .0em .0em .6em .2em;">Filtered ERD</h4> <div class="uk-panel uk-panel-scrollable" id="canvasContainer" style="margin-right: -1px; min-width: 30%;"> <canvas id="erdCanvas1" style="min-width: 30%;"></canvas> <div id="zoomButtons"> @@ -371,8 +444,8 @@ </div> <div style="flex: 0,7; display: flex; flex-direction: column;"> - <h4>Target ERD</h4> - <div class="uk-panel uk-panel-scrollable" id="canvasContainer" style="min-width: 20%; max-width: 70%;"> + <h4 style="margin: .0em .0em .6em .2em;">Target ERD</h4> + <div class="uk-panel" id="canvasContainer" style="overflow-y: scroll; min-width: 20%; width: 100%;"> <canvas id="erdCanvas2" style="min-width: 30%;"></canvas> <div id="zoomButtons"> <button class="uk-button uk-button-default uk-button-small custom-zoom-button"id="zoomInBtn2" uk-icon="plus-circle"></button> @@ -387,9 +460,9 @@ <li> <div style="display: flex; flex-direction: row; height: 87vh;"> - <div style="flex: 0,4; display: flex; flex-direction: column;"> - <h4>Target ERD</h4> - <div class="uk-panel uk-panel-scrollable" id="canvasContainer" style="margin-right: -1px; min-width: 30%;"> + <div id="scrollable-panel" style="display: flex; flex-direction: column;"> + <h4 style="margin: .0em .0em .6em .2em;">Target ERD</h4> + <div class="uk-panel" id="canvasContainer" style="overflow-y: auto;"> <canvas id="erdCanvas3" style="min-width: 30%;"></canvas> <div id="zoomButtons"> <button class="uk-button uk-button-default uk-button-small custom-zoom-button" id="zoomInBtn3" uk-icon="plus-circle"></button> @@ -398,41 +471,49 @@ </div> </div> - <div style="flex: 0,6; display: flex; width: 60%; max-width: 70%; flex-direction: column; border: 1px solid blue;"> + <div style="flex-grow: 1; padding-left: 10px; margin-top: 3px; display: flex; flex-direction: column;"> <fieldset> - <legend>Data Header</legend> + <legend style="margin: .2em .2em .4em -.4em; color:#5ea9e2; border-bottom: 1px solid gray; padding-bottom: 5px; padding-right: 3px;">Data Header</legend> <div class="mb-3"> <label class="form-label" style="margin-top: 14px">Type</label> <div class="uk-grid-small uk-child-width-auto uk-grid"> - <label><input class="uk-radio" type="radio" name="radio1"> Measurement </label><br><br> - <label><input class="uk-radio" type="radio" name="radio1"> Event </label><br><br> - <label><input class="uk-radio" type="radio" name="radio1"> Segment </label><br><br> - <label><input class="uk-radio" type="radio" name="radio1"> Segment Data </label><br><br> - <label><input class="uk-radio" type="radio" name="radio1"> Object </label> + <label><input class="uk-radio type-radio" type="radio" name="radio1" value="measurement" checked> Measurement </label><br><br> + <label><input class="uk-radio type-radio" type="radio" name="radio1" value="event"> Event </label><br><br> + <label><input class="uk-radio type-radio" type="radio" name="radio1" id="segmentType" value="segment"> Segment </label><br><br> + <label><input class="uk-radio type-radio" type="radio" name="radio1" value="segmentData"> Segment Data </label><br><br> + <label><input class="uk-radio type-radio" type="radio" name="radio1" id="objectType" value="object"> Object </label> </div> </div> - <div class="mb-3"> - <label class="form-label">Self-defined Label</label> - <input type="text" id="defined-label" class="form-control"> - <button class="btn btn-primary" onclick="addLabel()">add</button> + <div class="mb-3" id="object-column-selection" style="display: none;"> + <label class="form-label">Object name</label><br> + <select id="select_column_object" class="form-select headerSelect" name="column" style="margin-right: 5px; display: inline;"> + {% for column in columns %} + <option>Select a table first...</option> + <option value="{{label}}">{{ label }}</option> + {% endfor %} + </select><span style="color: red; font-size: 80%;">*</span> + </div> + + <div class="mb-3" id="self-defined-label-selection"> + <label class="form-label">Self-defined Label</label><br> + <input type="text" id="defined-label" class="form-control headerSelect"> + <button class="btn btn-primary headerButton" onclick="addLabel()">add</button> </div> - <div class="mb-3"> + <div class="mb-3" id="label-selection"> <label class="form-label">Label</label> - - <select id="select_column" class="form-select" name="column" onchange='handleLabelColumnClick(value)'> + <select id="select_column" class="form-select headerSelect" name="column" onchange='handleLabelColumnClick(value)'> {% for column in columns %} - <option>Column select...</option> + <option>Select a table first...</option> <option value="{{label}}">{{ label }}</option> {% endfor %} - </select> - - <select id=label_values class="form-select"> - <option>Label select...</option> + </select> + <select id=label_values class="form-select headerSelect " style="margin-top: 2px; margin-right: 5px; display: inline;"> + <option>Label select...</option> <optgroup id="defined_label_values" label="self-defined label"> {% for self_label in self_labels %} <option value="{{self_label}}">{{ self_label }}</option> @@ -444,46 +525,118 @@ <option value="{{label_value}}">{{ label_value }}</option> {% endfor %} </optgroup> - </select> + </select><span style="color: red; font-size: 80%;">*</span><br /> </div> - <div class="mb-3"> - <label class="form-label">Feature</label> - <select id="select_features" name = "value_column[]" data-placeholder="Value columns" multiple class="chosen-select" tabindex="8"> - <option value="GB">GB</option> - <option value="RU">RU</option> - <option value="RU">Hey</option> + <div class="mb-3" id="featuresSelection"> + <label class="form-label">Feature</label><br /> + <select id="select_features" name = "value_column[]" data-placeholder="Slect a table first..." multiple class="chosen-select" tabindex="4"> {% for column in columns %} <option>Column select...</option> <option value="{{label}}">{{ label }}</option> {% endfor %} </select> - - <script> $(".chosen-select").chosen(); </script> - <br> - <!-- <button type="submit" class="btn btn-primary">Submit</button> --> - + <script> $(".chosen-select").chosen({tabindex: 6}); $("#select_features").css('font-size','25px'); </script> + <span id="span"></span><span style="color: red; font-size: 80%;">*</span><br> </div> - <!-- <div class="mb-3"> - <div class="form-check"> - <input class="form-check-input" type="checkbox" id="disabledFieldsetCheck"> - <label class="form-check-label" for="disabledFieldsetCheck"> - Can't check this - </label> - </div> - </div> --> - <button type="submit" class="btn btn-primary">Submit</button> + + <button type="submit" class="btn btn-primary headerButton" onclick="submitDataHeader()" style="margin-top: -11px;">Submit</button> </fieldset> </div> </div> </li> + + <li> + <div style="display: flex; flex-direction: column; height: 87vh;"> + <div class="table-container" style="flex: 1; overflow-y: auto;"> + <table class="uk-table uk-table-striped" style="overflow-y: scroll;"> + <thead> + <tr> + <th>Table Heading</th> + <th>Table Heading</th> + <th>Table Heading</th> + </tr> + </thead> + <tbody> + <tr> + <td>Table Data</td> + <td>Table Data</td> + <td>Table Data</td> + </tr> + <tr> + <td>Table Data</td> + <td>Table Data</td> + <td>Table Data</td> + </tr> + <tr> + <td>Table Data</td> + <td>Table Data</td> + <td>Table Data</td> + </tr> + </tbody> + </table> + </div> + <div class="table-container" style="flex: 1; overflow-y: auto;"> + <div class="uk-overflow-auto"> + <table class="uk-table uk-table-hover uk-table-middle uk-table-divider" style="overflow-y: scroll;"> + <thead> + <tr> + <th class="uk-table-shrink"></th> + <th class="uk-table-shrink">Preserve</th> + <th class="uk-table-expand">Expand + Link</th> + <th class="uk-width-small">Truncate</th> + <th class="uk-table-shrink uk-text-nowrap">Shrink + Nowrap</th> + </tr> + </thead> + <tbody> + <tr> + <td><input class="uk-checkbox" type="checkbox" aria-label="Checkbox"></td> + <td><img class="uk-preserve-width uk-border-circle" src="images/avatar.jpg" width="40" height="40" alt=""></td> + <td class="uk-table-link"> + <a class="uk-link-reset" href="">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.</a> + </td> + <td class="uk-text-truncate">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.</td> + <td class="uk-text-nowrap">Lorem ipsum dolor</td> + </tr> + <tr> + <td><input class="uk-checkbox" type="checkbox" aria-label="Checkbox"></td> + <td><img class="uk-preserve-width uk-border-circle" src="images/avatar.jpg" width="40" height="40" alt=""></td> + <td class="uk-table-link"> + <a class="uk-link-reset" href="">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.</a> + </td> + <td class="uk-text-truncate">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.</td> + <td class="uk-text-nowrap">Lorem ipsum dolor</td> + </tr> + <tr> + <td><input class="uk-checkbox" type="checkbox" aria-label="Checkbox"></td> + <td><img class="uk-preserve-width uk-border-circle" src="images/avatar.jpg" width="40" height="40" alt=""></td> + <td class="uk-table-link"> + <a class="uk-link-reset" href="">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.</a> + </td> + <td class="uk-text-truncate">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.</td> + <td class="uk-text-nowrap">Lorem ipsum dolor</td> + </tr> + <tr> + <td><input class="uk-checkbox" type="checkbox" aria-label="Checkbox"></td> + <td><img class="uk-preserve-width uk-border-circle" src="images/avatar.jpg" width="40" height="40" alt=""></td> + <td class="uk-table-link"> + <a class="uk-link-reset" href="">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.</a> + </td> + <td class="uk-text-truncate">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.</td> + <td class="uk-text-nowrap">Lorem ipsum dolor</td> + </tr> + </tbody> + </table> + </div> + </div> + </div> + </li> </ul> <!-- </div> --> - <div class="custom-buttom-bar"> <div id="terminal" class="terminal"> <div id="terminal-header" class="terminal-header"> @@ -514,17 +667,16 @@ <p>Content for item 2.</p> </div> </li> - <!-- Add more items as needed --> </ul> - <!-- set_database.html --> + <!-- set_database.html <form method="post" action="/"> <div class="mb-3"> <label for="exampleInputPassword1" name="database_uri" class="form-label">Database URI</label> <input type="text" class="form-control" id="exampleInputPassword1" name="database_uri" placeholder="Enter Database URI"> <button type="submit" class="btn btn-primary">Submit</button> </div> - </form> + </form> --> <div id="resize-handle-left" class="resize-handle-left"></div> </div> @@ -595,6 +747,118 @@ // }); // } + + function submitDataHeader() { + var $ = function(id) { return document.getElementById(id); }; + var isValid = true; + + var radioSelect = document.querySelector('input[name="radio1"]:checked'); + console.log(radioSelect.value); + var label = $("label_values").value; + console.log(label); + var object_column = $("select_column_object").value; + console.log(object_column); + var tmp = $("select_features").selectedOptions; + var features_list = Array.from(tmp).map(({ value }) => value); + console.log(features_list); + + if (radioSelect.value == 'measurement') { + if (label == 'Label select...' || label == null || label == "") { + $("label_values").nextElementSibling.textContent = "This field is required."; + // alert("Please select a label"); + console.log("Label is required"); + if (features_list.length == 0 || features_list == null || features_list == []) { + $("span").nextElementSibling.textContent = "This field is required."; + // alert("Please select a feature"); + console.log("Feature is required"); + } + return; + } + if (features_list.length == 0 || features_list == null || features_list == []) { + $("span").nextElementSibling.textContent = "This field is required."; + // alert("Please select a feature"); + console.log("Feature is required"); + return; + } + } else if (radioSelect.value == 'event') { + if (label == 'Label select...' || label == null || label == "") { + $("label_values").nextElementSibling.textContent = "This field is required."; + // alert("Please select a label"); + console.log("Label is required"); + if (features_list.length == 0 || features_list == null || features_list == []) { + $("span").nextElementSibling.textContent = "This field is required."; + // alert("Please select a feature"); + console.log("Feature is required"); + } + return; + } + if (features_list.length == 0 || features_list == null || features_list == []) { + $("span").nextElementSibling.textContent = "This field is required."; + // alert("Please select a feature"); + console.log("Feature is required"); + return; + } + } else if (radioSelect.value == 'segment') { + if (label == 'Label select...' || label == null || label == '') { + $("label_values").nextElementSibling.textContent = "This field is required."; + // alert("Please select a label"); + console.log("Label is required"); + return; + } + } else if (radioSelect.value == 'segmentData') { + if (label == 'Label select...' || label == null || label == '') { + $("label_values").nextElementSibling.textContent = "This field is required."; + // alert("Please select a label"); + console.log("Label is required"); + if (features_list.length == 0 || features_list == null || features_list == []) { + $("span").nextElementSibling.textContent = "This field is required."; + // alert("Please select a feature"); + console.log("Feature is required"); + } + return; + } + if (features_list.length == 0 || features_list == null || features_list == []) { + $("span").nextElementSibling.textContent = "This field is required."; + // alert("Please select a feature"); + console.log("Feature is required"); + return; + } + } else if (radioSelect.value == 'object') { + if (object_column == 'Select a table first...' || object_column == null || object_column == '') { + $("select_column_object").nextElementSibling.textContent = "This field is required."; + // alert("Please select an object column"); + console.log("Object column is required"); + return; + } + } + + $("label_values").nextElementSibling.textContent = "*"; + $("span").nextElementSibling.textContent = "*"; + $("select_column_object").nextElementSibling.textContent = "*"; + + console.log("HERE"); + console.log(radioSelect, label, object_column, features_list); + + // Send the value to the server with fetch API + fetch('/add-data-header', { + method: 'POST', + body: JSON.stringify({ 'type': radioSelect.value, 'label': label, 'object_column': object_column, 'value_list': features_list}), + headers: { + 'Content-Type': 'application/json' + } + }) + .then(response => response.json()) + .then(data => { + + }) + .catch(error => { + // Handle any error that occurred during the fetch + console.error('Error:', error); + }); + + } + + function addLabel() { const labelValue = document.getElementById('defined-label').value; // Get the value of the input @@ -624,7 +888,7 @@ console.error('Error:', error); }); - labelValue.value = ''; // Clear the input field + document.getElementById('defined-label').value = ''; // Clear the input field } function toggleSidebar() { @@ -744,12 +1008,27 @@ // Display the table content in the terminal body document.querySelector('.terminal-body').innerHTML = data.html_table; + // Assign data.table_columns to the select element + const selectElement0 = document.getElementById('select_column_object'); + selectElement0.innerHTML = ''; + const optionElement0 = document.createElement('option'); + optionElement0.value = ''; + optionElement0.textContent = 'Column select...'; + selectElement0.appendChild(optionElement0); + // Add the table columns as options + data.table_columns.forEach(column => { + const optionElement = document.createElement('option'); + optionElement.value = column; + optionElement.textContent = column; + selectElement0.appendChild(optionElement); + }); + // Assign data.table_columns to the select element const selectElement = document.getElementById('select_column'); selectElement.innerHTML = ''; const optionElement = document.createElement('option'); optionElement.value = ''; - optionElement.textContent = 'Label column select'; + optionElement.textContent = 'Column select...'; selectElement.appendChild(optionElement); // Add the table columns as options data.table_columns.forEach(column => { @@ -764,6 +1043,7 @@ selectFeatures.innerHTML = ''; // Add the table columns as options data.feature_columns.forEach(column => { + console.log(column); const optionElement = document.createElement('option'); optionElement.value = column; optionElement.textContent = column; @@ -809,7 +1089,6 @@ .catch(error => console.error('Error:', error)); } - function makeTerminalResizable() { const terminal = document.getElementById('terminal'); const terminalHeader = document.getElementById('terminal-header'); @@ -833,26 +1112,52 @@ }); } - function showOptions(clickedItem) { - // Get the options container - var optionsContainer = document.getElementById('options-container'); - - // Position the options container near the clicked item - optionsContainer.style.display = 'block'; - optionsContainer.style.left = clickedItem.getBoundingClientRect().left + 'px'; - optionsContainer.style.top = clickedItem.getBoundingClientRect().bottom + 'px'; - - // Populate options specific to the clicked item - populateOptions(clickedItem.textContent.trim()); + function segmentTypeSelected() { + console.log('Segment type selected'); + if (this.value == 'segment') { + // Hide the features selection div + document.getElementById('featuresSelection').style.display = 'none'; + console.log('11Segment type selected'); + } else { + // Show the features selection div + document.getElementById('featuresSelection').style.display = 'block'; + console.log('22Segment type selected'); + } } - function populateOptions(tableName) { - // Logic to populate options based on the table name - // This will depend on the specific options you want to show - return 'abc'; - } + document.querySelectorAll('.type-radio').forEach(function(radio) { + radio.addEventListener('change', function() { + var $ = function(id) { return document.getElementById(id); }; + $("label_values").nextElementSibling.textContent = "*"; + $("span").nextElementSibling.textContent = "*"; + $("select_column_object").nextElementSibling.textContent = "*"; + var segmentType = document.getElementById('segmentType'); + var objectType = document.getElementById('objectType'); + var featuresSelection = document.getElementById('featuresSelection'); + var objectSelection = document.getElementById('object-column-selection'); + var selfdefinedlabelSelection = document.getElementById('self-defined-label-selection'); + var labelSelection = document.getElementById('label-selection'); + + if (segmentType.checked && radio.value === "segment") { + featuresSelection.style.display = 'none'; + objectSelection.style.display = 'none'; + selfdefinedlabelSelection.style.display = 'block'; + labelSelection.style.display = 'block'; + } else if (objectType.checked && objectType.value === "object"){ + featuresSelection.style.display = 'none'; + objectSelection.style.display = 'block'; + selfdefinedlabelSelection.style.display = 'none'; + labelSelection.style.display = 'none'; + } else { + featuresSelection.style.display = 'block'; + objectSelection.style.display = 'none'; + selfdefinedlabelSelection.style.display = 'block'; + labelSelection.style.display = 'block'; + } + }); + }); document.addEventListener('DOMContentLoaded', function() { // Show the ERD canvas @@ -891,6 +1196,24 @@ } }); + + document.getElementById('dropped_items').addEventListener('click', function(event) { + let target = event.target; + while (target != this) { + if (target.matches('.uk-card')) { + handleDroppedItemClick(target.textContent.trim()); + return; + } + target = target.parentNode; + } + }); + + + document.getElementById('close-terminal').addEventListener('click', function() { + closeTerminal(); + }); + + // document.getElementById('resetButton').addEventListener('click', function(event) { // event.preventDefault(); // Prevent the default form submission @@ -929,23 +1252,7 @@ // }); // Attach click event listener to each dropped item - document.getElementById('dropped_items').addEventListener('click', function(event) { - let target = event.target; - while (target != this) { - if (target.matches('.uk-card')) { - handleDroppedItemClick(target.textContent.trim()); - return; - } - target = target.parentNode; - } - - showOptions(target.textContent.trim()); - }); - - document.getElementById('close-terminal').addEventListener('click', function() { - closeTerminal(); - }); - + }); </script> </body>