diff --git a/.prettierignore b/.prettierignore index 156abbc6..c6942c65 100644 --- a/.prettierignore +++ b/.prettierignore @@ -3,7 +3,10 @@ node_modules/* .mypy_cache .pytest_cache .tox -web/static/lib/* + +/web/static/lib/* +!/web/static/lib/table/ +!/web/static/lib/scroll/ web/static/fonts/* web/static/css/* .lighthouserc/* diff --git a/package.json b/package.json index 605b9bff..20b39ffe 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "url": "github:atlas-bi/atlas-automation-hub" }, "scripts": { + "build": "gulp build", "commit": "git add . && pre-commit run ; git add . && cz --no-verify", "format": "prettier --config .prettierrc \"web/**/*.{ts,css,less,scss,js,json,md,yaml,html}\" --write", "install": "gulp build", diff --git a/runner/model.py b/runner/model.py index 779c9ea7..8ff4f60d 100644 --- a/runner/model.py +++ b/runner/model.py @@ -26,7 +26,7 @@ from typing import Optional from sqlalchemy.orm import declarative_base -from sqlalchemy.sql import functions as func +from sqlalchemy.sql import functions from .extensions import db @@ -59,7 +59,7 @@ class Login(db.Model): id = db.Column(db.Integer, primary_key=True, index=True) type_id = db.Column(db.Integer, db.ForeignKey(LoginType.id), nullable=True) username = db.Column(db.String(120), nullable=True) - login_date = db.Column(db.DateTime, server_default=func.now()) + login_date = db.Column(db.DateTime, server_default=functions.now()) @dataclass @@ -200,11 +200,11 @@ class Project(db.Model): passive_deletes=True, ) - created = db.Column(db.DateTime, server_default=func.now()) + created = db.Column(db.DateTime, server_default=functions.now()) creator_id = db.Column( db.Integer, db.ForeignKey(User.id), nullable=True, index=True ) - updated = db.Column(db.DateTime, onupdate=func.now()) + updated = db.Column(db.DateTime, onupdate=functions.now()) updater_id = db.Column( db.Integer, db.ForeignKey(User.id), nullable=True, index=True ) @@ -651,6 +651,7 @@ class ProjectParam(db.Model): key: Optional[str] = None value: Optional[str] = None sensitive: Optional[int] = None + project_id: Optional[int] = None id = db.Column(db.Integer, primary_key=True, index=True) key = db.Column(db.String(500), nullable=True) @@ -797,11 +798,11 @@ class Task(db.Model): last_run = db.Column(db.DateTime, nullable=True) last_run_job_id = db.Column(db.String(30), nullable=True, index=True) next_run = db.Column(db.DateTime, nullable=True, index=True) - created = db.Column(db.DateTime, server_default=func.now(), index=True) + created = db.Column(db.DateTime, server_default=functions.now(), index=True) creator_id = db.Column( db.Integer, db.ForeignKey(User.id), nullable=True, index=True ) - updated = db.Column(db.DateTime, onupdate=func.now(), index=True) + updated = db.Column(db.DateTime, onupdate=functions.now(), index=True) updater_id = db.Column( db.Integer, db.ForeignKey(User.id), nullable=True, index=True ) @@ -1079,6 +1080,7 @@ class TaskParam(db.Model): key: Optional[str] = None value: Optional[str] = None sensitive: Optional[int] = None + task_id: Optional[int] = None id = db.Column(db.Integer, primary_key=True, index=True) key = db.Column(db.String(500), nullable=True) diff --git a/scheduler/model.py b/scheduler/model.py index 779c9ea7..8ff4f60d 100644 --- a/scheduler/model.py +++ b/scheduler/model.py @@ -26,7 +26,7 @@ from typing import Optional from sqlalchemy.orm import declarative_base -from sqlalchemy.sql import functions as func +from sqlalchemy.sql import functions from .extensions import db @@ -59,7 +59,7 @@ class Login(db.Model): id = db.Column(db.Integer, primary_key=True, index=True) type_id = db.Column(db.Integer, db.ForeignKey(LoginType.id), nullable=True) username = db.Column(db.String(120), nullable=True) - login_date = db.Column(db.DateTime, server_default=func.now()) + login_date = db.Column(db.DateTime, server_default=functions.now()) @dataclass @@ -200,11 +200,11 @@ class Project(db.Model): passive_deletes=True, ) - created = db.Column(db.DateTime, server_default=func.now()) + created = db.Column(db.DateTime, server_default=functions.now()) creator_id = db.Column( db.Integer, db.ForeignKey(User.id), nullable=True, index=True ) - updated = db.Column(db.DateTime, onupdate=func.now()) + updated = db.Column(db.DateTime, onupdate=functions.now()) updater_id = db.Column( db.Integer, db.ForeignKey(User.id), nullable=True, index=True ) @@ -651,6 +651,7 @@ class ProjectParam(db.Model): key: Optional[str] = None value: Optional[str] = None sensitive: Optional[int] = None + project_id: Optional[int] = None id = db.Column(db.Integer, primary_key=True, index=True) key = db.Column(db.String(500), nullable=True) @@ -797,11 +798,11 @@ class Task(db.Model): last_run = db.Column(db.DateTime, nullable=True) last_run_job_id = db.Column(db.String(30), nullable=True, index=True) next_run = db.Column(db.DateTime, nullable=True, index=True) - created = db.Column(db.DateTime, server_default=func.now(), index=True) + created = db.Column(db.DateTime, server_default=functions.now(), index=True) creator_id = db.Column( db.Integer, db.ForeignKey(User.id), nullable=True, index=True ) - updated = db.Column(db.DateTime, onupdate=func.now(), index=True) + updated = db.Column(db.DateTime, onupdate=functions.now(), index=True) updater_id = db.Column( db.Integer, db.ForeignKey(User.id), nullable=True, index=True ) @@ -1079,6 +1080,7 @@ class TaskParam(db.Model): key: Optional[str] = None value: Optional[str] = None sensitive: Optional[int] = None + task_id: Optional[int] = None id = db.Column(db.Integer, primary_key=True, index=True) key = db.Column(db.String(500), nullable=True) diff --git a/web/static/lib/table/logs.js b/web/static/lib/table/logs.js index fd9ebbec..c0351a2e 100644 --- a/web/static/lib/table/logs.js +++ b/web/static/lib/table/logs.js @@ -47,6 +47,45 @@ } }; } + var scroll_ajax = null; + function loader(container, url) { + // if within x of top and no "at-start" class, then get more logs. + if ( + container.querySelector('.ss-content') && + container.querySelector('.ss-content').scrollTop < 500 && + !container.classList.contains('at-start') && + !container.querySelector('div.loader') + ) { + var loader = undefined; + if (container.querySelector('.ss-content').scrollTop == 0) { + loader = document.createElement('div'); + loader.classList.add('loader', 'm-5'); + loader.setAttribute('style', 'position:absolute;top:-30px;left:-13px;'); + container.insertBefore(loader, container.firstChild); + } + + // get logs + + if (scroll_ajax) { + scroll_ajax.abort(); + } + scroll_ajax = new XMLHttpRequest(); + + scroll_ajax.open('get', url + '?lt=' + log_id_min, true); + scroll_ajax.send(); + + scroll_ajax.onload = function () { + try { + appendLogs(JSON.parse(this.responseText), container, url); + if (loader !== undefined && loader.parentElement) { + loader.parentElement.removeChild(loader); + } + } catch (e) { + console.log(e); + } + }; + } + } function loadLogs(arr, el, url) { var box = document.createElement('div'); @@ -64,56 +103,18 @@ container.setAttribute('ss-container', 'ss-container'); container.setAttribute('style', 'height:100%'); - var scroll_ajax = null; container.addEventListener( 'scroll', - debounce(function () { - // if within x of top and no "at-start" class, then get more logs. - if ( - container.querySelector('.ss-content').scrollTop < 500 && - !container.classList.contains('at-start') - ) { - // add loader - var loader = container.querySelector('div.loader'); - - if (!loader) { - loader = document.createElement('div'); - loader.classList.add('loader', 'm-5'); - loader.setAttribute( - 'style', - 'position:absolute;top:-30px;left:-13px;', - ); - container.insertBefore(loader, container.firstChild); - } - - // get logs - - if (scroll_ajax) { - scroll_ajax.abort(); - } - scroll_ajax = new XMLHttpRequest(); - - scroll_ajax.open('get', url + '?lt=' + log_id_min, true); - scroll_ajax.send(); - - scroll_ajax.onload = function () { - try { - appendLogs(JSON.parse(this.responseText), container); - if (loader !== undefined && loader.parentElement) { - loader.parentElement.removeChild(loader); - } - } catch (e) { - console.log(e); - } - }; - } + debounce(() => { + loader(container, url); }, 10), ); + box.appendChild(container); el.innerHTML = ''; el.appendChild(box); - appendLogs(arr, container); + appendLogs(arr, container, url); // trigger scroll document.dispatchEvent( @@ -148,7 +149,7 @@ q.onload = function () { try { - appendLogs(JSON.parse(this.responseText), container); + appendLogs(JSON.parse(this.responseText), container, url); } catch (e) { console.log(e); } @@ -160,7 +161,7 @@ })(container, url); } - function appendLogs(arr, container) { + function appendLogs(arr, container, url) { var empty_msg = 'No data to show.', current_date = new Date().toLocaleString().replace(',', ''); //.replace(/:\d\d\s/, " "); @@ -326,14 +327,7 @@ } }); - if (group[x]['location'] == 'before') { - updated.parentElement.insertBefore( - nav, - updated.parentElement.firstChild, - ); - } else { - updated.parentElement.insertBefore(nav, updated); - } + // left left = document.createElement('div'); left.classList.add( 'level-left', @@ -430,6 +424,24 @@ } left.appendChild(message); + + if (group[x]['location'] == 'before') { + updated.parentElement.insertBefore( + nav, + updated.parentElement.firstChild, + ); + + // preserve scroll position + if (container.querySelector('.ss-content')) { + var height = nav.clientHeight; + container.querySelector('.ss-content').scrollTop += height; + } else { + console.log('no scroller yet'); + } + } else { + updated.parentElement.insertBefore(nav, updated); + } + // scroll to bottom if has attribute ss-bottom if (container.hasAttribute('ss-bottom')) { scroller = container.querySelector('.ss-content'); @@ -439,5 +451,6 @@ }); } } + loader(container, url); } })((window.rhcTable = window.rhcTable || {})); diff --git a/web/static/lib/table/table.js b/web/static/lib/table/table.js index 7e62d6fc..189064d1 100644 --- a/web/static/lib/table/table.js +++ b/web/static/lib/table/table.js @@ -365,7 +365,9 @@ })(reload, el); } - var autoReload = el.querySelector('input.switch') ? el.querySelector('input.switch').parentElement : null; + var autoReload = el.querySelector('input.switch') + ? el.querySelector('input.switch').parentElement + : null; var reloadTimer; if (autoReload) { /* auto reload */