mirror of https://github.com/MISP/misp-modules
add: [website] tree view history
Flask session store history and after save it's store in DBpull/592/merge
parent
b38e4feb37
commit
0364deccaa
|
@ -1,3 +1,4 @@
|
||||||
|
import json
|
||||||
from .. import db
|
from .. import db
|
||||||
|
|
||||||
|
|
||||||
|
@ -32,13 +33,38 @@ class Session_db(db.Model):
|
||||||
query_date = db.Column(db.DateTime, index=True)
|
query_date = db.Column(db.DateTime, index=True)
|
||||||
|
|
||||||
def to_json(self):
|
def to_json(self):
|
||||||
return
|
json_dict = {
|
||||||
|
"id": self.id,
|
||||||
|
"uuid": self.uuid,
|
||||||
|
"modules": json.loads(self.modules_list),
|
||||||
|
"query_enter": self.query_enter,
|
||||||
|
"input_query": self.input_query,
|
||||||
|
"config_module": json.loads(self.config_module),
|
||||||
|
"result": json.loads(self.result),
|
||||||
|
"nb_errors": self.nb_errors,
|
||||||
|
"query_date": self.query_date.strftime('%Y-%m-%d')
|
||||||
|
}
|
||||||
|
return json_dict
|
||||||
|
|
||||||
|
def history_json(self):
|
||||||
|
json_dict = {
|
||||||
|
"uuid": self.uuid,
|
||||||
|
"modules": json.loads(self.modules_list),
|
||||||
|
"query": self.query_enter,
|
||||||
|
"input": self.input_query,
|
||||||
|
"query_date": self.query_date.strftime('%Y-%m-%d')
|
||||||
|
}
|
||||||
|
return json_dict
|
||||||
|
|
||||||
|
|
||||||
class History(db.Model):
|
class History(db.Model):
|
||||||
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
||||||
session_id = db.Column(db.Integer, index=True)
|
session_id = db.Column(db.Integer, index=True)
|
||||||
|
|
||||||
|
class History_Tree(db.Model):
|
||||||
|
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
||||||
|
session_uuid = db.Column(db.String(36), index=True)
|
||||||
|
tree = db.Column(db.String)
|
||||||
|
|
||||||
class Config(db.Model):
|
class Config(db.Model):
|
||||||
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
||||||
|
|
|
@ -15,6 +15,13 @@ home_blueprint = Blueprint(
|
||||||
def home():
|
def home():
|
||||||
return render_template("home.html")
|
return render_template("home.html")
|
||||||
|
|
||||||
|
@home_blueprint.route("/home/<sid>", methods=["GET", "POST"])
|
||||||
|
def home_query(sid):
|
||||||
|
if "query" in request.args:
|
||||||
|
query = request.args.get("query")
|
||||||
|
return render_template("home.html", query=query, sid=sid)
|
||||||
|
return render_template("404.html")
|
||||||
|
|
||||||
@home_blueprint.route("/query/<sid>")
|
@home_blueprint.route("/query/<sid>")
|
||||||
def query(sid):
|
def query(sid):
|
||||||
session = HomeModel.get_session(sid)
|
session = HomeModel.get_session(sid)
|
||||||
|
@ -24,7 +31,7 @@ def query(sid):
|
||||||
query_loc = session.query_enter
|
query_loc = session.query_enter
|
||||||
else:
|
else:
|
||||||
for s in SessionModel.sessions:
|
for s in SessionModel.sessions:
|
||||||
if s.id == sid:
|
if s.uuid == sid:
|
||||||
flag = True
|
flag = True
|
||||||
query_loc = s.query
|
query_loc = s.query
|
||||||
session=s
|
session=s
|
||||||
|
@ -64,6 +71,7 @@ def run_modules():
|
||||||
if "input" in request.json:
|
if "input" in request.json:
|
||||||
if "modules" in request.json:
|
if "modules" in request.json:
|
||||||
session = SessionModel.Session_class(request.json)
|
session = SessionModel.Session_class(request.json)
|
||||||
|
HomeModel.set_flask_session(session, request.json["parent_id"])
|
||||||
session.start()
|
session.start()
|
||||||
SessionModel.sessions.append(session)
|
SessionModel.sessions.append(session)
|
||||||
return jsonify(session.status()), 201
|
return jsonify(session.status()), 201
|
||||||
|
@ -79,7 +87,7 @@ def status(sid):
|
||||||
return jsonify(HomeModel.get_status_db(sess))
|
return jsonify(HomeModel.get_status_db(sess))
|
||||||
else:
|
else:
|
||||||
for s in SessionModel.sessions:
|
for s in SessionModel.sessions:
|
||||||
if s.id == sid:
|
if s.uuid == sid:
|
||||||
return jsonify(s.status())
|
return jsonify(s.status())
|
||||||
return jsonify({'message': 'Scan session not found'}), 404
|
return jsonify({'message': 'Scan session not found'}), 404
|
||||||
|
|
||||||
|
@ -91,7 +99,7 @@ def result(sid):
|
||||||
return jsonify(HomeModel.get_result_db(sess))
|
return jsonify(HomeModel.get_result_db(sess))
|
||||||
else:
|
else:
|
||||||
for s in SessionModel.sessions:
|
for s in SessionModel.sessions:
|
||||||
if s.id == sid:
|
if s.uuid == sid:
|
||||||
return jsonify(s.get_result())
|
return jsonify(s.get_result())
|
||||||
return jsonify({'message': 'Scan session not found'}), 404
|
return jsonify({'message': 'Scan session not found'}), 404
|
||||||
|
|
||||||
|
@ -146,3 +154,34 @@ def get_history():
|
||||||
"""Get all history"""
|
"""Get all history"""
|
||||||
histories = HomeModel.get_history()
|
histories = HomeModel.get_history()
|
||||||
return histories
|
return histories
|
||||||
|
|
||||||
|
@home_blueprint.route("/history_session", methods=["GET"])
|
||||||
|
def history_session():
|
||||||
|
"""View all history"""
|
||||||
|
return render_template("history_session.html", tree_view=False)
|
||||||
|
|
||||||
|
@home_blueprint.route("/get_history_session", methods=["GET"])
|
||||||
|
def get_history_session():
|
||||||
|
"""Get all history"""
|
||||||
|
histories = HomeModel.get_history_session()
|
||||||
|
if histories:
|
||||||
|
return histories
|
||||||
|
return {}
|
||||||
|
|
||||||
|
@home_blueprint.route("/save_history/<sid>", methods=["GET"])
|
||||||
|
def save_history(sid):
|
||||||
|
return HomeModel.save_history_core(sid)
|
||||||
|
|
||||||
|
|
||||||
|
@home_blueprint.route("/history_tree", methods=["GET"])
|
||||||
|
def history_tree():
|
||||||
|
"""View all history"""
|
||||||
|
return render_template("history_session.html", tree_view=True)
|
||||||
|
|
||||||
|
@home_blueprint.route("/get_history_tree", methods=["GET"])
|
||||||
|
def get_history_tree():
|
||||||
|
"""Get all history"""
|
||||||
|
histories = HomeModel.get_history_tree()
|
||||||
|
if histories:
|
||||||
|
return histories
|
||||||
|
return {}
|
|
@ -1,7 +1,10 @@
|
||||||
import json
|
import json
|
||||||
from .utils.utils import query_get_module
|
from .utils.utils import query_get_module, isUUID
|
||||||
from . import db
|
from . import db
|
||||||
from .db_class.db import History, Module, Config, Module_Config, Session_db
|
from .db_class.db import History, Module, Config, Module_Config, Session_db, History_Tree
|
||||||
|
from . import sess
|
||||||
|
from flask import session as sess
|
||||||
|
from sqlalchemy import desc
|
||||||
|
|
||||||
|
|
||||||
def get_module(mid):
|
def get_module(mid):
|
||||||
|
@ -29,7 +32,7 @@ def get_module_config_both(mid, cid):
|
||||||
return Module_Config.query.filter_by(module_id=mid, config_id=cid).first()
|
return Module_Config.query.filter_by(module_id=mid, config_id=cid).first()
|
||||||
|
|
||||||
def get_session(sid):
|
def get_session(sid):
|
||||||
"""Return a session by id"""
|
"""Return a session by uuid"""
|
||||||
return Session_db.query.filter_by(uuid=sid).first()
|
return Session_db.query.filter_by(uuid=sid).first()
|
||||||
|
|
||||||
def get_modules():
|
def get_modules():
|
||||||
|
@ -138,14 +141,142 @@ def get_result_db(session):
|
||||||
def get_history():
|
def get_history():
|
||||||
"""Return history"""
|
"""Return history"""
|
||||||
histories_list = list()
|
histories_list = list()
|
||||||
histories = History.query.all()
|
histories = History.query.order_by(desc(History.id))
|
||||||
for history in histories:
|
for history in histories:
|
||||||
session = Session_db.query.get(history.session_id)
|
session = Session_db.query.get(history.session_id)
|
||||||
histories_list.append({
|
histories_list.append(session.history_json())
|
||||||
"uuid": session.uuid,
|
|
||||||
"query": session.query_enter,
|
|
||||||
"modules": json.loads(session.modules_list),
|
|
||||||
"input": session.input_query,
|
|
||||||
"query_date": session.query_date.strftime('%Y-%m-%d')
|
|
||||||
})
|
|
||||||
return histories_list
|
return histories_list
|
||||||
|
|
||||||
|
|
||||||
|
def util_set_flask_session(parent_id, loc_session, current_session):
|
||||||
|
if parent_id == loc_session["uuid"]:
|
||||||
|
loc_json = {
|
||||||
|
"uuid": current_session.uuid,
|
||||||
|
"modules": current_session.modules_list,
|
||||||
|
"query": current_session.query,
|
||||||
|
"input": current_session.input_query,
|
||||||
|
"query_date": current_session.query_date.strftime('%Y-%m-%d')
|
||||||
|
}
|
||||||
|
loc_session["children"].append(loc_json)
|
||||||
|
return True
|
||||||
|
elif "children" in loc_session:
|
||||||
|
return deep_explore(loc_session["children"], parent_id, current_session)
|
||||||
|
|
||||||
|
def deep_explore(session_dict, parent_id, current_session):
|
||||||
|
for loc_session in session_dict:
|
||||||
|
if not "children" in loc_session:
|
||||||
|
loc_session["children"] = list()
|
||||||
|
if util_set_flask_session(parent_id, loc_session, current_session):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def set_flask_session(current_session, parent_id):
|
||||||
|
current_query = sess.get("current_query")
|
||||||
|
if not current_query or current_query not in sess:
|
||||||
|
loc_json = {
|
||||||
|
"uuid": current_session.uuid,
|
||||||
|
"modules": current_session.modules_list,
|
||||||
|
"query": current_session.query,
|
||||||
|
"input": current_session.input_query,
|
||||||
|
"query_date": current_session.query_date.strftime('%Y-%m-%d')
|
||||||
|
}
|
||||||
|
|
||||||
|
sess["current_query"] = current_session.uuid
|
||||||
|
sess[sess.get("current_query")] = loc_json
|
||||||
|
sess[sess.get("current_query")]["children"] = list()
|
||||||
|
else:
|
||||||
|
# sess["uuid"]
|
||||||
|
loc_session = sess.get(sess.get("current_query"))
|
||||||
|
if not "children" in loc_session:
|
||||||
|
loc_session["children"] = list()
|
||||||
|
if not util_set_flask_session(parent_id, loc_session, current_session):
|
||||||
|
sess["current_query"] = current_session.uuid
|
||||||
|
|
||||||
|
def get_history_session():
|
||||||
|
current_query = sess.get("current_query")
|
||||||
|
loc_list = list()
|
||||||
|
if current_query:
|
||||||
|
# If current query have no children then don't display it
|
||||||
|
# It's already save in history
|
||||||
|
# Only parent-child tree structure is in flask session
|
||||||
|
current_query_value = sess.get(sess.get("current_query"))
|
||||||
|
if current_query_value and current_query_value["children"]:
|
||||||
|
loc_list.append(current_query_value)
|
||||||
|
for q in sess:
|
||||||
|
if isUUID(q):
|
||||||
|
# If query have no children then don't display it
|
||||||
|
q_value = sess.get(q)
|
||||||
|
if q_value["children"]:
|
||||||
|
if not q == current_query:
|
||||||
|
loc_list.append(q_value)
|
||||||
|
|
||||||
|
return loc_list
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def util_save_history(session):
|
||||||
|
loc_dict = dict()
|
||||||
|
loc_dict[session["uuid"]] = []
|
||||||
|
|
||||||
|
if "children" in session and session["children"]:
|
||||||
|
for child in session["children"]:
|
||||||
|
loc_dict[session["uuid"]].append(util_save_history(child))
|
||||||
|
return loc_dict
|
||||||
|
|
||||||
|
|
||||||
|
def save_history_core(sid):
|
||||||
|
"""Save history from session to db"""
|
||||||
|
if sid in sess:
|
||||||
|
session = sess.get(sid)
|
||||||
|
# Doesn't already exist
|
||||||
|
history_tree_db = History_Tree.query.filter_by(session_uuid=session["uuid"]).first()
|
||||||
|
if not history_tree_db:
|
||||||
|
if "children" in session and session["children"]:
|
||||||
|
# Get all children before add to db
|
||||||
|
loc_dict = util_save_history(session)
|
||||||
|
h = History_Tree(
|
||||||
|
session_uuid = session["uuid"],
|
||||||
|
tree=json.dumps(loc_dict)
|
||||||
|
)
|
||||||
|
db.session.add(h)
|
||||||
|
db.session.commit()
|
||||||
|
return {"message": "History Save", 'toast_class': "success-subtle"}
|
||||||
|
return {"message": "No children", 'toast_class': "warning-subtle"}
|
||||||
|
# Save same session but with new value
|
||||||
|
elif not json.loads(history_tree_db.tree) == session:
|
||||||
|
if "children" in session and session["children"]:
|
||||||
|
# Get all children before add to db
|
||||||
|
loc_dict = util_save_history(session)
|
||||||
|
history_tree_db.tree = json.dumps(loc_dict)
|
||||||
|
db.session.commit()
|
||||||
|
return {"message": "History updated", 'toast_class': "success-subtle"}
|
||||||
|
return {"message": "History already saved", 'toast_class': "warning-subtle"}
|
||||||
|
return {"message": "Session not found", 'toast_class': "danger-subtle"}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def util_get_history_tree(child):
|
||||||
|
loc_child = list(child.keys())[0]
|
||||||
|
loc_session = get_session(loc_child)
|
||||||
|
loc_json = loc_session.history_json()
|
||||||
|
loc_json["children"] = list()
|
||||||
|
if child[loc_child]:
|
||||||
|
for s_child in child[loc_child]:
|
||||||
|
loc_json["children"].append(util_get_history_tree(s_child))
|
||||||
|
return loc_json
|
||||||
|
|
||||||
|
def get_history_tree():
|
||||||
|
"""Return all histories saved as tree"""
|
||||||
|
histories_tree = History_Tree.query.order_by(desc(History_Tree.id))
|
||||||
|
loc_dict = list()
|
||||||
|
for history_tree in histories_tree:
|
||||||
|
tree = json.loads(history_tree.tree)
|
||||||
|
|
||||||
|
loc_session = get_session(history_tree.session_uuid)
|
||||||
|
loc_json = loc_session.history_json()
|
||||||
|
loc_json["children"] = list()
|
||||||
|
for child in tree[history_tree.session_uuid]:
|
||||||
|
loc_json["children"].append(util_get_history_tree(child))
|
||||||
|
loc_dict.append(loc_json)
|
||||||
|
return loc_dict
|
||||||
|
|
|
@ -14,7 +14,7 @@ sessions = list()
|
||||||
|
|
||||||
class Session_class:
|
class Session_class:
|
||||||
def __init__(self, request_json) -> None:
|
def __init__(self, request_json) -> None:
|
||||||
self.id = str(uuid4())
|
self.uuid = str(uuid4())
|
||||||
self.thread_count = 4
|
self.thread_count = 4
|
||||||
self.jobs = Queue(maxsize=0)
|
self.jobs = Queue(maxsize=0)
|
||||||
self.threads = []
|
self.threads = []
|
||||||
|
@ -63,7 +63,7 @@ class Session_class:
|
||||||
registered = len(self.result)
|
registered = len(self.result)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'id': self.id,
|
'id': self.uuid,
|
||||||
'total': total,
|
'total': total,
|
||||||
'complete': complete,
|
'complete': complete,
|
||||||
'remaining': remaining,
|
'remaining': remaining,
|
||||||
|
@ -110,7 +110,7 @@ class Session_class:
|
||||||
else:
|
else:
|
||||||
send_to = {"module": work[1], self.input_query: self.query, "config": loc_config}
|
send_to = {"module": work[1], self.input_query: self.query, "config": loc_config}
|
||||||
res = query_post_query(send_to)
|
res = query_post_query(send_to)
|
||||||
print(res)
|
# print(res)
|
||||||
if "error" in res:
|
if "error" in res:
|
||||||
self.nb_errors += 1
|
self.nb_errors += 1
|
||||||
self.result[work[1]] = res
|
self.result[work[1]] = res
|
||||||
|
@ -124,7 +124,7 @@ class Session_class:
|
||||||
def save_info(self):
|
def save_info(self):
|
||||||
"""Save info in the db"""
|
"""Save info in the db"""
|
||||||
s = Session_db(
|
s = Session_db(
|
||||||
uuid=str(self.id),
|
uuid=str(self.uuid),
|
||||||
modules_list=json.dumps(self.modules_list),
|
modules_list=json.dumps(self.modules_list),
|
||||||
query_enter=self.query,
|
query_enter=self.query,
|
||||||
input_query=self.input_query,
|
input_query=self.input_query,
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
|
|
||||||
const { ref, nextTick } = Vue
|
|
||||||
export default {
|
export default {
|
||||||
name: "History_view",
|
name: "History_view",
|
||||||
delimiters: ['[[', ']]'],
|
delimiters: ['[[', ']]'],
|
||||||
|
@ -7,36 +6,63 @@ export default {
|
||||||
history: Object,
|
history: Object,
|
||||||
key_loop: Number
|
key_loop: Number
|
||||||
},
|
},
|
||||||
setup(props) {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return {
|
|
||||||
|
|
||||||
}
|
|
||||||
},
|
|
||||||
template: `
|
template: `
|
||||||
<div class="list-group" style="margin-bottom: 20px;">
|
<div style="display: flex;">
|
||||||
<a :href="'/query/'+history.uuid" class="list-group-item list-group-item-action">
|
<div style="list-style-type: none; padding: 10px; font-size: large; margin-left: 13px" >
|
||||||
<div class="d-flex w-100 justify-content-between">
|
<a v-if="'children' in history && history['children'].length" data-bs-toggle="collapse" style="color: black;" :href="'#collapseChild-'+history.uuid" role="button" aria-expanded="true" :aria-controls="'collapseChild-'+history.uuid">
|
||||||
<h5 class="mb-1">[[key_loop+1]]- [[history.query]]</h5>
|
<i class="fa-solid fa-caret-down"></i>
|
||||||
<small><i>[[history.uuid]]</i></small>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<p class="mb-1" style="color: green;"><u>Input Attribute</u>:</p>
|
<a style="text-decoration: none; color: black;" data-bs-toggle="collapse" :href="'#collapse'+history.uuid" role="button" aria-expanded="false" :aria-controls="'collapse'+history.uuid">
|
||||||
<div>[[history.input]]</div>
|
<ul class="list-group list-group-horizontal" style="padding-top: 5px;">
|
||||||
<br>
|
<li class="list-group-item">
|
||||||
<p class="mb-1" style="color: #2000ff;"><u>Modules</u>:</p>
|
<h5>[[history.query]]</h5>
|
||||||
<div>
|
</li>
|
||||||
<template v-for="module in history.modules">[[module]],</template>
|
<li class="list-group-item">
|
||||||
</div>
|
<h5 style="color: brown"><u>Input Attributes</u></h5>
|
||||||
|
[[history.input]]
|
||||||
|
</li>
|
||||||
<div class="d-flex w-100 justify-content-between">
|
<li class="list-group-item">
|
||||||
<div></div>
|
<h5 style="color: brown"><u>Modules</u></h5>
|
||||||
<small><i>[[history.query_date]]</i></small>
|
<template v-for="module in history.modules">[[module]],</template>
|
||||||
</div>
|
</li>
|
||||||
|
</ul
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="collapse" :id="'collapse'+history.uuid" style="width: 70%; margin-left: 30px">
|
||||||
|
<div class="card card-body">
|
||||||
|
<div class="d-flex w-100 justify-content-between">
|
||||||
|
<h5 class="mb-1">[[history.query]]</h5>
|
||||||
|
<small><i>[[history.uuid]]</i></small>
|
||||||
|
</div>
|
||||||
|
<p class="mb-1" style="color: green;"><u>Input Attribute</u>:</p>
|
||||||
|
<div>[[history.input]]</div>
|
||||||
|
<br>
|
||||||
|
<p class="mb-1" style="color: #2000ff;"><u>Modules</u>:</p>
|
||||||
|
<div>
|
||||||
|
<template v-for="module in history.modules">[[module]],</template>
|
||||||
|
</div>
|
||||||
|
<div></div>
|
||||||
|
<div class="d-flex w-100 justify-content-between">
|
||||||
|
<div><a :href="'/query/'+history.uuid">See results</a></div>
|
||||||
|
<small><i>[[history.query_date]]</i></small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="collapse show" :id="'collapseChild-'+history.uuid">
|
||||||
|
<ul style="list-style-type: none;">
|
||||||
|
<li>
|
||||||
|
<div class="card-body">
|
||||||
|
<template v-for="h, key in history['children']">
|
||||||
|
<history_view :history="h" :key_loop="key" />
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
`
|
`
|
||||||
}
|
}
|
|
@ -9,20 +9,40 @@
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
<div v-if="history">
|
<div v-if="history">
|
||||||
<template v-for="h, key in history">
|
<template v-for="h, key in history">
|
||||||
<history_view :history="h" :key_loop="key" />
|
<div class="list-group" style="margin-bottom: 20px;">
|
||||||
|
<a :href="'/query/'+h.uuid" class="list-group-item list-group-item-action">
|
||||||
|
<div class="d-flex w-100 justify-content-between">
|
||||||
|
<h5 class="mb-1">[[key+1]]- [[h.query]]</h5>
|
||||||
|
<small><i>[[h.uuid]]</i></small>
|
||||||
|
</div>
|
||||||
|
<p class="mb-1" style="color: green;"><u>Input Attribute</u>:</p>
|
||||||
|
<div>[[h.input]]</div>
|
||||||
|
<br>
|
||||||
|
<p class="mb-1" style="color: #2000ff;"><u>Modules</u>:</p>
|
||||||
|
<div>
|
||||||
|
<template v-for="module in h.modules">[[module]],</template>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="d-flex w-100 justify-content-between">
|
||||||
|
<div></div>
|
||||||
|
<small><i>[[h.query_date]]</i></small>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<span id="goTop">[<a href="#top">Go Back Top</a>]</span>
|
<span id="goTop">[<a href="#top">Go Back Top</a>]</span>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block script %}
|
{% block script %}
|
||||||
<script type="module">
|
<script type="module">
|
||||||
const { createApp, ref, onMounted, nextTick, defineComponent} = Vue
|
const { createApp, ref, onMounted, nextTick, defineComponent} = Vue
|
||||||
import {display_toast, message_list} from '/static/js/toaster.js'
|
import {message_list} from '/static/js/toaster.js'
|
||||||
import history_view from '/static/js/history_view.js'
|
import history_view from '/static/js/history_view.js'
|
||||||
createApp({
|
createApp({
|
||||||
delimiters: ['[[', ']]'],
|
delimiters: ['[[', ']]'],
|
||||||
|
|
|
@ -0,0 +1,137 @@
|
||||||
|
<!--
|
||||||
|
Author: David Cruciani
|
||||||
|
-->
|
||||||
|
|
||||||
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<input hidden value="{{tree_view}}" id="tree_view">
|
||||||
|
<h1 id="top">History</h1>
|
||||||
|
<small v-if="!tree_view"><i>All histories present here will be delete at the end of the session</i></small>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<template v-if="Object.keys(history).length">
|
||||||
|
<div v-for="his, key in history" style="background-color: white; border: 1px solid #808080a1; border-radius: 8px; padding: 10px; margin-top: 17px;">
|
||||||
|
<div class="d-flex w-100 justify-content-between">
|
||||||
|
<h4># [[key + 1]]</h4>
|
||||||
|
<button v-if="!tree_view" class="btn btn-primary btn-sm" @click="save_history(his)">Save</button>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
<div style="display: flex;">
|
||||||
|
<a style="padding: 10px; font-size: large; color: black;" v-if="'children' in his && his['children'].length" data-bs-toggle="collapse" :href="'#collapseChild-'+his.uuid" aria-expanded="true" :aria-controls="'collapseChild-'+his.uuid">
|
||||||
|
<i class="fa-solid fa-caret-down"></i>
|
||||||
|
</a>
|
||||||
|
<a style="text-decoration: none; color: black;" data-bs-toggle="collapse" :href="'#collapse'+his.uuid" role="button" aria-expanded="false" :aria-controls="'collapse'+his.uuid">
|
||||||
|
<ul class="list-group list-group-horizontal">
|
||||||
|
<li class="list-group-item">
|
||||||
|
<h4>[[his.query]]</h4>
|
||||||
|
</li>
|
||||||
|
<li class="list-group-item">
|
||||||
|
<h5 style="color: brown"><u>Input Attributes</u></h5>
|
||||||
|
[[his.input]]
|
||||||
|
</li>
|
||||||
|
<li class="list-group-item">
|
||||||
|
<h5 style="color: brown"><u>Modules</u></h5>
|
||||||
|
<template v-for="module in his.modules">[[module]],</template>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="collapse" :id="'collapse'+his.uuid" style="width: 70%; margin-left:30px">
|
||||||
|
<div class="card card-body">
|
||||||
|
<div class="d-flex w-100 justify-content-between">
|
||||||
|
<h5 class="mb-1">[[his.query]]</h5>
|
||||||
|
<small><i>[[his.uuid]]</i></small>
|
||||||
|
</div>
|
||||||
|
<p class="mb-1" style="color: green;"><u>Input Attribute</u>:</p>
|
||||||
|
<div>[[his.input]]</div>
|
||||||
|
<br>
|
||||||
|
<p class="mb-1" style="color: #2000ff;"><u>Modules</u>:</p>
|
||||||
|
<div>
|
||||||
|
<template v-for="module in his.modules">[[module]],</template>
|
||||||
|
</div>
|
||||||
|
<div></div>
|
||||||
|
<div class="d-flex w-100 justify-content-between">
|
||||||
|
<div><a :href="'/query/'+his.uuid">See results</a></div>
|
||||||
|
<small><i>[[his.query_date]]</i></small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="collapse show" :id="'collapseChild-'+his.uuid">
|
||||||
|
<ul style="list-style-type: none;">
|
||||||
|
<li>
|
||||||
|
<div class="card-body">
|
||||||
|
<template v-for="h, key in his['children']">
|
||||||
|
<history_view :history="h" :key_loop="key" />
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<div v-else>
|
||||||
|
<i>No History</i>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<span id="goTop">[<a href="#top">Go Back Top</a>]</span>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block script %}
|
||||||
|
<script type="module">
|
||||||
|
const { createApp, ref, onMounted, nextTick, defineComponent} = Vue
|
||||||
|
import {display_toast, message_list} from '/static/js/toaster.js'
|
||||||
|
import history_view from '/static/js/history_view.js'
|
||||||
|
createApp({
|
||||||
|
delimiters: ['[[', ']]'],
|
||||||
|
components: {
|
||||||
|
history_view
|
||||||
|
},
|
||||||
|
setup() {
|
||||||
|
const history = ref({})
|
||||||
|
const tree_view = ref(false)
|
||||||
|
|
||||||
|
async function get_history_session(){
|
||||||
|
let res = await fetch("/get_history_session")
|
||||||
|
let loc = await res.json()
|
||||||
|
history.value = loc
|
||||||
|
}
|
||||||
|
async function get_history_tree(){
|
||||||
|
let res = await fetch("/get_history_tree")
|
||||||
|
let loc = await res.json()
|
||||||
|
history.value = loc
|
||||||
|
}
|
||||||
|
|
||||||
|
async function save_history(history){
|
||||||
|
const res = await fetch("/save_history/" + history.uuid)
|
||||||
|
display_toast(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
tree_view.value = $("#tree_view").val()
|
||||||
|
if(tree_view.value == "True"){
|
||||||
|
get_history_tree()
|
||||||
|
tree_view.value = true
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
tree_view.value = false
|
||||||
|
get_history_session()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
return {
|
||||||
|
message_list,
|
||||||
|
history,
|
||||||
|
tree_view,
|
||||||
|
save_history,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).mount('.container')
|
||||||
|
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
|
@ -15,7 +15,8 @@
|
||||||
<br>
|
<br>
|
||||||
<div style="width:50%; transform: translate(50%, 0);">
|
<div style="width:50%; transform: translate(50%, 0);">
|
||||||
<div>
|
<div>
|
||||||
<input type="text" id="process-query" placeholder="Enter here..." autofocus class="form-control" style="border-radius: 5px;" />
|
<input type="hidden" id="parent_id" value="{{sid}}">
|
||||||
|
<input type="text" value="{{query}}" id="process-query" placeholder="Enter here..." autofocus class="form-control" style="border-radius: 5px;" />
|
||||||
</div>
|
</div>
|
||||||
<span v-if="status_site" id="status">[[status_site]]</span>
|
<span v-if="status_site" id="status">[[status_site]]</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -101,7 +102,8 @@
|
||||||
|
|
||||||
let result_dict = {"modules": $("#modules_select").val(),
|
let result_dict = {"modules": $("#modules_select").val(),
|
||||||
"input": $("#input_select").val(),
|
"input": $("#input_select").val(),
|
||||||
"query": current_query.value
|
"query": current_query.value,
|
||||||
|
"parent_id": $("#parent_id").val()
|
||||||
}
|
}
|
||||||
result_dict["config"] = {}
|
result_dict["config"] = {}
|
||||||
for(let el in config_query.value){
|
for(let el in config_query.value){
|
||||||
|
|
|
@ -127,6 +127,7 @@
|
||||||
<div>
|
<div>
|
||||||
Value: [[attr.value]]
|
Value: [[attr.value]]
|
||||||
</div>
|
</div>
|
||||||
|
<a v-if="attr.type != 'counter' && attr.type != 'datetime'" :href="'/home/{{sid}}?query='+attr.value">query</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<hr>
|
<hr>
|
||||||
|
|
|
@ -18,6 +18,12 @@
|
||||||
<a style="margin-top: 30px;" href="/history" class="list-group-item list-group-item-action py-2 ripple">
|
<a style="margin-top: 30px;" href="/history" class="list-group-item list-group-item-action py-2 ripple">
|
||||||
<i class="fa-solid fa-clock-rotate-left fa-fw me-3"></i><span>History</span>
|
<i class="fa-solid fa-clock-rotate-left fa-fw me-3"></i><span>History</span>
|
||||||
</a>
|
</a>
|
||||||
|
<a style="margin-top: 30px;" href="/history_session" class="list-group-item list-group-item-action py-2 ripple">
|
||||||
|
<i class="fa-solid fa-clock fa-fw me-3"></i><span>History Session</span>
|
||||||
|
</a>
|
||||||
|
<a style="margin-top: 30px;" href="/history_tree" class="list-group-item list-group-item-action py-2 ripple">
|
||||||
|
<i class="fa-solid fa-timeline fa-fw me-3"></i><span>History Tree</span>
|
||||||
|
</a>
|
||||||
<a style="margin-top: 30px;" href="/modules_config" class="list-group-item list-group-item-action py-2 ripple">
|
<a style="margin-top: 30px;" href="/modules_config" class="list-group-item list-group-item-action py-2 ripple">
|
||||||
<i class="fa-solid fa-gear fa-fw me-3"></i><span>Config</span>
|
<i class="fa-solid fa-gear fa-fw me-3"></i><span>Config</span>
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# import os
|
# import os
|
||||||
# import uuid
|
import uuid
|
||||||
import json
|
import json
|
||||||
import requests
|
import requests
|
||||||
# import jsonschema
|
# import jsonschema
|
||||||
|
@ -31,12 +31,12 @@ def query_post_query(data, headers={'Content-type': 'application/json'}):
|
||||||
return r.json()
|
return r.json()
|
||||||
|
|
||||||
|
|
||||||
# def isUUID(uid):
|
def isUUID(uid):
|
||||||
# try:
|
try:
|
||||||
# uuid.UUID(str(uid))
|
uuid.UUID(str(uid))
|
||||||
# return True
|
return True
|
||||||
# except ValueError:
|
except ValueError:
|
||||||
# return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
# def form_to_dict(form):
|
# def form_to_dict(form):
|
||||||
|
|
Loading…
Reference in New Issue