This commit is contained in:
Dennis Kerschus 2023-06-13 13:19:05 +02:00
parent c3fcce1527
commit 7c6b05710c
34 changed files with 130185 additions and 0 deletions

View File

@ -0,0 +1,164 @@
/* -*- indent-tabs-mode: nil; tab-width: 4; -*- */
/* Greenlet object interface */
#ifndef Py_GREENLETOBJECT_H
#define Py_GREENLETOBJECT_H
#include <Python.h>
#ifdef __cplusplus
extern "C" {
#endif
/* This is deprecated and undocumented. It does not change. */
#define GREENLET_VERSION "1.0.0"
#ifndef GREENLET_MODULE
#define implementation_ptr_t void*
#endif
typedef struct _greenlet {
PyObject_HEAD
PyObject* weakreflist;
PyObject* dict;
implementation_ptr_t pimpl;
} PyGreenlet;
#define PyGreenlet_Check(op) (op && PyObject_TypeCheck(op, &PyGreenlet_Type))
/* C API functions */
/* Total number of symbols that are exported */
#define PyGreenlet_API_pointers 12
#define PyGreenlet_Type_NUM 0
#define PyExc_GreenletError_NUM 1
#define PyExc_GreenletExit_NUM 2
#define PyGreenlet_New_NUM 3
#define PyGreenlet_GetCurrent_NUM 4
#define PyGreenlet_Throw_NUM 5
#define PyGreenlet_Switch_NUM 6
#define PyGreenlet_SetParent_NUM 7
#define PyGreenlet_MAIN_NUM 8
#define PyGreenlet_STARTED_NUM 9
#define PyGreenlet_ACTIVE_NUM 10
#define PyGreenlet_GET_PARENT_NUM 11
#ifndef GREENLET_MODULE
/* This section is used by modules that uses the greenlet C API */
static void** _PyGreenlet_API = NULL;
# define PyGreenlet_Type \
(*(PyTypeObject*)_PyGreenlet_API[PyGreenlet_Type_NUM])
# define PyExc_GreenletError \
((PyObject*)_PyGreenlet_API[PyExc_GreenletError_NUM])
# define PyExc_GreenletExit \
((PyObject*)_PyGreenlet_API[PyExc_GreenletExit_NUM])
/*
* PyGreenlet_New(PyObject *args)
*
* greenlet.greenlet(run, parent=None)
*/
# define PyGreenlet_New \
(*(PyGreenlet * (*)(PyObject * run, PyGreenlet * parent)) \
_PyGreenlet_API[PyGreenlet_New_NUM])
/*
* PyGreenlet_GetCurrent(void)
*
* greenlet.getcurrent()
*/
# define PyGreenlet_GetCurrent \
(*(PyGreenlet * (*)(void)) _PyGreenlet_API[PyGreenlet_GetCurrent_NUM])
/*
* PyGreenlet_Throw(
* PyGreenlet *greenlet,
* PyObject *typ,
* PyObject *val,
* PyObject *tb)
*
* g.throw(...)
*/
# define PyGreenlet_Throw \
(*(PyObject * (*)(PyGreenlet * self, \
PyObject * typ, \
PyObject * val, \
PyObject * tb)) \
_PyGreenlet_API[PyGreenlet_Throw_NUM])
/*
* PyGreenlet_Switch(PyGreenlet *greenlet, PyObject *args)
*
* g.switch(*args, **kwargs)
*/
# define PyGreenlet_Switch \
(*(PyObject * \
(*)(PyGreenlet * greenlet, PyObject * args, PyObject * kwargs)) \
_PyGreenlet_API[PyGreenlet_Switch_NUM])
/*
* PyGreenlet_SetParent(PyObject *greenlet, PyObject *new_parent)
*
* g.parent = new_parent
*/
# define PyGreenlet_SetParent \
(*(int (*)(PyGreenlet * greenlet, PyGreenlet * nparent)) \
_PyGreenlet_API[PyGreenlet_SetParent_NUM])
/*
* PyGreenlet_GetParent(PyObject* greenlet)
*
* return greenlet.parent;
*
* This could return NULL even if there is no exception active.
* If it does not return NULL, you are responsible for decrementing the
* reference count.
*/
# define PyGreenlet_GetParent \
(*(PyGreenlet* (*)(PyGreenlet*)) \
_PyGreenlet_API[PyGreenlet_GET_PARENT_NUM])
/*
* deprecated, undocumented alias.
*/
# define PyGreenlet_GET_PARENT PyGreenlet_GetParent
# define PyGreenlet_MAIN \
(*(int (*)(PyGreenlet*)) \
_PyGreenlet_API[PyGreenlet_MAIN_NUM])
# define PyGreenlet_STARTED \
(*(int (*)(PyGreenlet*)) \
_PyGreenlet_API[PyGreenlet_STARTED_NUM])
# define PyGreenlet_ACTIVE \
(*(int (*)(PyGreenlet*)) \
_PyGreenlet_API[PyGreenlet_ACTIVE_NUM])
/* Macro that imports greenlet and initializes C API */
/* NOTE: This has actually moved to ``greenlet._greenlet._C_API``, but we
keep the older definition to be sure older code that might have a copy of
the header still works. */
# define PyGreenlet_Import() \
{ \
_PyGreenlet_API = (void**)PyCapsule_Import("greenlet._C_API", 0); \
}
#endif /* GREENLET_MODULE */
#ifdef __cplusplus
}
#endif
#endif /* !Py_GREENLETOBJECT_H */

5
.venv/pyvenv.cfg Normal file
View File

@ -0,0 +1,5 @@
home = C:\Python311
include-system-site-packages = false
version = 3.11.4
executable = C:\Python311\python.exe
command = C:\Python311\python.exe -m venv --upgrade C:\users\denker\Documents\udvikling\Python\FlowAnalyser\.venv

26
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,26 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Python: Flask",
"type": "python",
"request": "launch",
"module": "flask",
"env": {
"FLASK_APP": "FlowAnalyserMain.py",
"FLASK_DEBUG": "1"
},
"args": [
"run",
"--no-debugger",
"--no-reload"
],
"jinja": true,
"justMyCode": true
}
]
}

15
FlowTest.py Normal file
View File

@ -0,0 +1,15 @@
from inn import getEngine
import markdown
def test():
#engine = getEngine()
text = "# Title"+"\n"
text+= "~~~mermaid\n"
text+= "gantt\n"
text+="~~~"
html=markdown.markdown(text, extensions=['md_mermaid'])
print(html)
return html

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

4
env.py Normal file
View File

@ -0,0 +1,4 @@
server = 'bi-dsa-udv\dsa' # to
database = 'udv_denker'
username = 'admindenker'
password = 'biadmin#kode4rmO1'

BIN
favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 KiB

17
inn.py Normal file
View File

@ -0,0 +1,17 @@
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import Session,registry
from sqlalchemy import sql,Table,select,MetaData
import urllib
def getEngine(database):
server = 'bi-dsa-udv\dsa' # to specify an alternate port
username = 'admindenker'
password = 'biadmin#kode4rm2'
connection_string = "DRIVER={SQL Server};Database="+database+";SERVER="+server
connection_string = urllib.parse.quote_plus(connection_string)
connection_string = "mssql+pyodbc:///?odbc_connect=%s" % connection_string
engine = create_engine(connection_string, echo = True)
return engine

BIN
requirements.txt Normal file

Binary file not shown.

346
static/css/mermaid.css Normal file
View File

@ -0,0 +1,346 @@
/* Flowchart variables */
/* Sequence Diagram variables */
/* Gantt chart variables */
div.mermaid svg
{
display: block;
margin-right: auto;
margin-left: auto;
}
.mermaid .label
{
color: #333;
}
div.mermaid .node rect,
div.mermaid .node circle,
div.mermaid .node ellipse,
div.mermaid .node polygon
{
fill: #ececff;
stroke: #ccf;
stroke-width: 1px;
}
div.mermaid .edgePath .path
{
stroke: #333;
}
div.mermaid .edgeLabel
{
background-color: #e8e8e8;
}
div.mermaid .cluster rect
{
fill: #ffffde !important;
rx: 4 !important;
stroke: #aa3 !important;
stroke-width: 1px !important;
}
div.mermaid .cluster text
{
fill: #333;
}
div.mermaid .actor
{
stroke: #ccf;
fill: #ececff;
}
div.mermaid text.actor
{
fill: black;
stroke: none;
}
div.mermaid .actor-line
{
stroke: grey;
}
div.mermaid .messageLine0
{
stroke-width: 1.5;
stroke-dasharray: '2 2';
marker-end: 'url(#arrowhead)';
stroke: #333;
}
div.mermaid .messageLine1
{
stroke-width: 1.5;
stroke-dasharray: '2 2';
stroke: #333;
}
#arrowhead
{
fill: #333;
}
#crosshead path
{
fill: #333 !important;
stroke: #333 !important;
}
div.mermaid .messageText
{
fill: #333;
stroke: none;
}
div.mermaid .labelBox
{
stroke: #ccf;
fill: #ececff;
}
div.mermaid .labelText
{
fill: black;
stroke: none;
}
div.mermaid .loopText
{
fill: black;
stroke: none;
}
div.mermaid .loopLine
{
stroke-width: 2;
stroke-dasharray: '2 2';
marker-end: 'url(#arrowhead)';
stroke: #ccf;
}
div.mermaid .note
{
stroke: #aa3;
fill: #fff5ad;
}
div.mermaid .noteText
{
font-family: 'trebuchet ms', verdana, arial;
font-size: 14px;
fill: black;
stroke: none;
}
/** Section styling */
div.mermaid .section
{
opacity: .2;
stroke: none;
}
div.mermaid .section0
{
fill: rgba(102, 102, 255, .49);
}
div.mermaid .section2
{
fill: #fff400;
}
div.mermaid .section1,
div.mermaid .section3
{
opacity: .2;
fill: white;
}
div.mermaid .sectionTitle0
{
fill: #333;
}
div.mermaid .sectionTitle1
{
fill: #333;
}
div.mermaid .sectionTitle2
{
fill: #333;
}
div.mermaid .sectionTitle3
{
fill: #333;
}
div.mermaid .sectionTitle
{
font-size: 11px;
text-anchor: start;
text-height: 14px;
}
/* Grid and axis */
div.mermaid .grid .tick
{
opacity: .3;
stroke: lightgrey;
shape-rendering: crispEdges;
}
div.mermaid .grid path
{
stroke-width: 0;
}
/* Today line */
div.mermaid .today
{
fill: none;
stroke: red;
stroke-width: 2px;
}
/* Task styling */
/* Default task */
div.mermaid .task
{
stroke-width: 2;
}
div.mermaid .taskText
{
font-size: 11px;
text-anchor: middle;
}
div.mermaid .taskTextOutsideRight
{
font-size: 11px;
fill: black;
text-anchor: start;
}
div.mermaid .taskTextOutsideLeft
{
font-size: 11px;
fill: black;
text-anchor: end;
}
/* Specific task settings for the sections*/
div.mermaid .taskText0,
div.mermaid .taskText1,
div.mermaid .taskText2,
div.mermaid .taskText3
{
fill: white;
}
div.mermaid .task0,
div.mermaid .task1,
div.mermaid .task2,
div.mermaid .task3
{
fill: #8a90dd;
stroke: #534fbc;
}
div.mermaid .taskTextOutside0,
div.mermaid .taskTextOutside2
{
fill: black;
}
div.mermaid .taskTextOutside1,
div.mermaid .taskTextOutside3
{
fill: black;
}
/* Active task */
div.mermaid .active0,
div.mermaid .active1,
div.mermaid .active2,
div.mermaid .active3
{
fill: #bfc7ff;
stroke: #534fbc;
}
div.mermaid .activeText0,
div.mermaid .activeText1,
div.mermaid .activeText2,
div.mermaid .activeText3
{
fill: black !important;
}
/* Completed task */
div.mermaid .done0,
div.mermaid .done1,
div.mermaid .done2,
div.mermaid .done3
{
stroke: grey;
fill: lightgrey;
stroke-width: 2;
}
div.mermaid .doneText0,
div.mermaid .doneText1,
div.mermaid .doneText2,
div.mermaid .doneText3
{
fill: black !important;
}
/* Tasks on the critical line */
div.mermaid .crit0,
div.mermaid .crit1,
div.mermaid .crit2,
div.mermaid .crit3
{
stroke: #f88;
fill: red;
stroke-width: 2;
}
div.mermaid .activeCrit0,
div.mermaid .activeCrit1,
div.mermaid .activeCrit2,
div.mermaid .activeCrit3
{
stroke: #f88;
fill: #bfc7ff;
stroke-width: 2;
}
div.mermaid .doneCrit0,
div.mermaid .doneCrit1,
div.mermaid .doneCrit2,
div.mermaid .doneCrit3
{
cursor: pointer;
stroke: #f88;
fill: lightgrey;
stroke-width: 2;
shape-rendering: crispEdges;
}
div.mermaid .doneCritText0,
div.mermaid .doneCritText1,
div.mermaid .doneCritText2,
div.mermaid .doneCritText3
{
fill: black !important;
}
div.mermaid .activeCritText0,
div.mermaid .activeCritText1,
div.mermaid .activeCritText2,
div.mermaid .activeCritText3
{
fill: black !important;
}
div.mermaid .titleText
{
font-size: 18px;
text-anchor: middle;
fill: black;
}
/*
*/
div.mermaid .node text
{
font-family: 'trebuchet ms', verdana, arial;
font-size: 14px;
}
div.mermaidTooltip
{
font-family: 'trebuchet ms', verdana, arial;
font-size: 12px;
position: absolute;
z-index: 100;
max-width: 200px;
padding: 2px;
text-align: center;
pointer-events: none;
border: 1px solid #aa3;
border-radius: 2px;
background: #ffffde;
}

54
static/css/style.css Normal file
View File

@ -0,0 +1,54 @@
html,body,#wrapper {
width: 100%;
height: 100%;
margin: 0px;
}
.chart {
font-family: Arial, sans-serif;
font-size: 12px;
}
.axis path,.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.bar {
fill: #33b5e5;
}
.bar-failed {
fill: #CC0000;
}
.bar-running {
fill: #669900;
}
.bar-succeeded {
fill: #33b5e5;
}
.bar-killed {
fill: #ffbb33;
}
#forkme_banner {
display: block;
position: absolute;
top: 0;
right: 10px;
z-index: 10;
padding: 10px 50px 10px 10px;
color: #fff;
background:
url('http://dk8996.github.io/Gantt-Chart/images/blacktocat.png')
#0090ff no-repeat 95% 50%;
font-weight: 700;
box-shadow: 0 0 10px rgba(0, 0, 0, .5);
border-bottom-left-radius: 2px;
border-bottom-right-radius: 2px;
text-decoration: none;
}

14924
static/mermaid.core.js Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

114244
static/mermaid.js Normal file

File diff suppressed because one or more lines are too long

65
static/mermaid.js.map Normal file

File diff suppressed because one or more lines are too long

25
static/mermaid.min.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

21
sysjob2html.py Normal file
View File

@ -0,0 +1,21 @@
from typing import Union,List
from inn import getEngine
import markdown
from sysjobs import *
def getHtml(sysjob: List[Union[Sysjobs,Sysjobhistory]]) -> str:
resReturn: str=''
resReturn = "# Title\n"
resReturn+= "~~~mermaid\n"
resReturn+= "gantt\n"
#resReturn+= "dateFormat YYYY-MM-DD H HH\n"
for a in sysjob:
resReturn+=a[0].name + ' : ' + str(a[1].getStartTime()) + ',' + str(a[1].getRunDurationInHourMinSec())+ '\n'
resReturn+="~~~"
resReturn=markdown.markdown(resReturn, extensions=['md_mermaid'])
resReturn=resReturn.replace('<script>mermaid.initialize({startOnLoad:true});</script>','')
return resReturn
def getJson(sysjob: List[Union[Sysjobs,Sysjobhistory]]):
return ''

141
sysjobs.py Normal file
View File

@ -0,0 +1,141 @@
#from __future__ import annotations
from typing import List
from sqlalchemy import BOOLEAN, Column,INTEGER,NVARCHAR, ForeignKey,Select, and_, or_
from sqlalchemy.dialects.mssql import UNIQUEIDENTIFIER, TINYINT
from sqlalchemy.orm import relationship,Session,Mapped,mapped_column
from sqlalchemy.ext.declarative import declarative_base
from datetime import datetime,timedelta,time
import json
from json import JSONEncoder
#import sysjobhistory
import inn
class MyEncoder(JSONEncoder):
def default(self, obj):
if(isinstance(obj,Sysjobs) or isinstance(obj,Sysjobhistory)):
return obj.getDict()
else:
return object.__dict__
Base = declarative_base()
class Sysjobs(Base):
__tablename__ = "sysjobs"
job_id: Mapped[str] = mapped_column(UNIQUEIDENTIFIER,primary_key=True)
name=Column(NVARCHAR(128))
enabled=Column(TINYINT)
sysjobhistories: Mapped[List["Sysjobhistory"]] = relationship(back_populates="sysjob")
dataflow_jobs: Mapped[List["DataflowManagement_JobListe"]] = relationship(back_populates="sysjob")
def __iter__(self):
yield from {
"job_id": self.job_id,
"name": self.name
}.items()
def __iter__(self):
yield from {
"job_id": str(self.job_id),
"name": self.name
}.items()
def __str__(self):
return json.dumps(self.getDict())
def getDict(self):
return {'job_id': str(self.job_id), 'name': self.name}
def __repr__(self):
return self.__str__()
def getTest(self,session: Session):
stmt = Select(Sysjobs).join(Sysjobhistory).where(Sysjobhistory.run_date>20230601).distinct()
print(stmt)
with Session(engine) as session:
row : Sysjobs
res = session.execute(stmt).all()
for row in res:
print(row.Sysjobs.name + ' ' + str(row.Sysjobhistory.run_date) + ' ' + str(row.Sysjobhistory.run_time))
def getNattensKoersel(session) -> List['Sysjobs']:
natStat=(datetime.today()-timedelta(days=1)).replace(hour=20,minute=0,second=0,microsecond=0)
resReturn: List['Sysjobs'] = list()
stmt = Select(Sysjobs,Sysjobhistory).join(DataflowManagement_JobListe).join(Sysjobhistory).where(Sysjobhistory.step_id==0).where(DataflowManagement_JobListe.Aktiv==1).where(or_(and_(Sysjobhistory.run_date>=int((natStat.strftime('%Y%m%d'))),(Sysjobhistory.run_time>=int((natStat.strftime('%H%M%S'))))),Sysjobhistory.run_date>int((datetime.today().strftime('%Y%m%d'))))).distinct()
row : Sysjobs
res = session.execute(stmt).all()
# resReturn=[x[0] for x in res]
return res
class Sysjobhistory(Base):
__tablename__ = "sysjobhistory"
instance_id=Column(INTEGER,primary_key=True)
job_id: Mapped[str] = mapped_column(ForeignKey("sysjobs.job_id"))
step_id = Column(INTEGER)
step_name=Column(NVARCHAR(128))
run_date=Column(INTEGER)
run_time=Column(INTEGER)
run_duration=Column(INTEGER)
sysjob: Mapped["Sysjobs"] = relationship(back_populates="sysjobhistories")
def __iter__(self):
yield from {
"instance_id": self.instance_id,
"job_id": str(self.job_id),
"step_id": self.step_id,
"step_name": self.step_name,
"getStartTime": str(self.getStartTime()),
"getEndTime": str(self.getEndTime())
}.items()
def __str__(self):
return json.dumps(self.getDict())
def getDict(self):
return {'instance_id': self.instance_id, 'job_id': str(self.job_id), 'step_id' : self.step_id, 'step_name': self.step_name, 'getStartTime': str(self.getStartTime()), 'getEndTime': str(self.getEndTime())}
def __repr__(self):
return self.__str__()
def getTest(self):
engine=inn.getEngine("msdb")
# stmt = Select(Sysjobhistory)
# with Session(engine) as session:
# for row in session.execute(stmt).first():
# print(row)
def getStartTime(self) -> datetime:
resReturn: datetime
resReturn = datetime.fromisoformat(str(self.run_date)[0:4]+'-'+ str(self.run_date)[4:6]+'-'+str(self.run_date)[6:8]+' '+str(1000000+self.run_time)[1:3]+':'+str(1000000+self.run_time)[3:5]+':'+str(1000000+self.run_time)[5:7])
return resReturn
def getEndTime(self) -> datetime:
resReturn: datetime
resReturn = self.getStartTime()+timedelta(seconds=self.getRunDurationInSec())
return resReturn
def getRunDurationInSec(self) -> int:
resReturn: int
resReturn = 3600*(int(str(self.run_duration+1000000)[1:3]))+60*(int(str(self.run_duration+1000000)[3:5]))+(int(str(self.run_duration+1000000)[3:5]))
return resReturn
def getRunDurationInHourMinSec(self) -> str:
resReturn: str
resReturn=str(timedelta(seconds=self.getRunDurationInSec()))
return resReturn
def getRunHistory(self,Sysjob):
engine=inn.getEngine("msdb")
stmt = Select(Sysjobhistory).join(Sysjobhistory).filter(Sysjob)
with Session(engine) as session:
row : Sysjobs
res = session.execute(stmt).all()
print(res.__len__)
class DataflowManagement_JobListe(Base):
__tablename__ = "JobListe"
__table_args__ = { "schema": "dataflowmanagement.flw" }
JobID: Mapped[str] = mapped_column(ForeignKey("sysjobs.job_id"),primary_key=True)
Aktiv=Column(BOOLEAN)
sysjob: Mapped["Sysjobs"] = relationship(back_populates="dataflow_jobs")

9
templates/index.html Normal file
View File

@ -0,0 +1,9 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>FlaskBlog</title>
</head>
<body>
</body>
</html>

57
test.md Normal file
View File

@ -0,0 +1,57 @@
```mermaid
gantt
title Writing my thesis
dateFormat YYYY-MM-DD H HH
axisFormat %X
BI - Flow - DSI_CPR : 2023-06-11 20:01:58,0:08:08
BI - Flow - DSO_PAS_MDS : 2023-06-11 22:26:41,0:00:00
BI - Flow - DSO_SharedDimensions_Personale : 2023-06-11 22:21:15,0:03:03
BI - Flow - DSO_SharedDimensions_Sikkerhed : 2023-06-11 22:41:49,0:04:04
BI - Flow - DSI_IFDB_BOOKING : 2023-06-11 22:00:00,0:11:11
BI - Flow - DSI_IFDB_PAS_LPR3 : 2023-06-11 22:00:00,0:21:21
BI - Flow - DSO_SharedDimensions_Dimensions_ALLE : 2023-06-11 22:25:54,0:26:26
BI - Flow - DSI_SSI : 2023-06-11 20:01:14,0:02:02
BI - Flow - DSO_PAS_PRE : 2023-06-11 22:25:52,0:00:00
BI - Flow - DSO_SharedDimensions_SKSBrowser : 2023-06-11 22:00:39,0:03:03
BI - Flow - DSI_IFDB_MEDICIN : 2023-06-11 22:00:00,0:13:13
BI - Flow - DSO_SharedDimensions_Bridge_IFDB : 2023-06-11 22:52:16,0:10:10
BI - Flow - DSO_PAS_DIM : 2023-06-11 22:27:25,0:08:08
BI - Flow - DSO_SharedDimensions_Borger : 2023-06-11 22:21:14,0:13:13
BI - Flow - DSI_IFDB_SHARED : 2023-06-11 22:00:00,0:00:00
BI - Flow - Batch Start Daglig kl. 20.00 : 2023-06-11 20:00:00,0:02:02
BI - Flow - DSI_SST : 2023-06-11 20:01:56,0:01:01
BI - Flow - DSO_SharedDimensions_Organisation : 2023-06-11 22:21:12,0:20:20
BI - Flow - DPA_SharedDimensions : 2023-06-11 23:03:04,0:07:07
BI - Flow - DSO_SharedDimensions_Dimensions_PRE : 2023-06-11 22:21:18,0:04:04
BI - Flow - DPA_SharedDimensions_Sikkerhed : 2023-06-11 22:45:54,0:01:01
BI - Flow - DSI_IFDB_PAS_SFI : 2023-06-11 22:00:00,0:05:05
BI - Flow - DSO_PAS_FACT : 2023-06-11 23:03:00,0:47:47
BI - Flow - DSO_SharedDimensions_Shared : 2023-06-11 20:01:29,0:00:00
BI - Flow - DPA_SharedDimensions_Shared : 2023-06-11 20:01:45,0:00:00
BI - Flow - DSI_IFDB_PAS : 2023-06-11 22:00:00,0:14:14
BI - Flow - DSI_LUNAADM : 2023-06-11 20:01:13,0:03:03
```
titleTopMargin:25,
barHeight:20,
barGap:4,
topPadding:50,
leftPadding:75,
gridLineStartPadding:35,
fontSize:11,
fontFamily:'"Open-Sans", "sans-serif"',
numberSectionStyles:4,
<h1>Welcome to FlaskBlog</h1>
{{ test|safe }}
<script src="https://unpkg.com/mermaid@8.14.0/dist/mermaid.min.js">
mermaid.ganttConfig = {
titleTopMargin: 25,
barHeight: 20,
barGap: 4,
topPadding: 75,
sidePadding: 75,
};
mermaid.initialize({startOnLoad:true});
</script>

2
tmp.txt Normal file
View File

@ -0,0 +1,2 @@
tmp.txt
<script src="{{ url_for('static', filename= 'mermaid.min.js') }}"></script>