Skip to content

Commit

Permalink
dashboard first step
Browse files Browse the repository at this point in the history
status view for task and claim (#27)
  • Loading branch information
FrancescoGalasso committed Sep 1, 2022
1 parent bba92d3 commit 578d57f
Show file tree
Hide file tree
Showing 12 changed files with 619 additions and 18 deletions.
4 changes: 3 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@
'email_validator',
'markdown',
'unidecode',
'flask-migrate']
'flask-migrate',
'flask_restful',
]

SETUP_KW_ARGS = {
'name': 'flask_tracker',
Expand Down
28 changes: 28 additions & 0 deletions src/flask_tracker/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,34 @@ def upload_attachments(self, ): # pylint: disable=no-self-use

return resp

@flask_admin.expose('/reports', methods=('GET', ))
@check_login
def report_query_test(self):

session = MODELS_GLOBAL_CONTEXT['session']

tasks = [t.object_to_json(include_relationship=1) for t in session.query(Task)]
# tasks = [t for t in session.query(Task)]
# project_names = [p.name for p in session.query(Project).limit(50)]
# order_names = [o.name for o in session.query(Order).limit(50)]
# user_names = [o.name for o in session.query(User).limit(50)]
# logging.warning(f'tasks >> {tasks}')


ctx = {
# 'projects': project_names,
# 'orders': order_names,
# 'users': user_names,
# 'report_title': 'report 000',
# 'report_results': []
'tasks': tasks,
'total_tasks': len(tasks)
}

ret = self.render('admin/reports.html', **ctx)

return ret


def init_admin(app, db): # pylint: disable=too-many-statements

Expand Down
90 changes: 90 additions & 0 deletions src/flask_tracker/api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# coding: utf-8

# pylint: disable=missing-docstring
# pylint: disable=logging-format-interpolation
# pylint: disable=line-too-long
# pylint: disable=invalid-name
# pylint: disable=broad-except
# pylint: disable=logging-fstring-interpolation, consider-using-f-string

import logging
# import traceback
import json

import flask_tracker.models

from flask_restful import Resource, Api # pylint: disable=import-error
from flask import Response # pylint: disable=import-error

URL_PREFIX = '/api/v1/'
DB_SESSION = None


def frmt_model_obj(model_obj, excluded_fields,
include_relationship=0, worktimes=False, milestone=False):
model_json_str = model_obj.object_to_json(
include_relationship=include_relationship,
excluded_fields=excluded_fields
)

model_dict = json.loads(model_json_str)
if worktimes:
wtimes = model_dict.get('worktimes')
model_dict['worktimes'] = sum([float(wt.get('duration')) for wt in wtimes])
if milestone:
milestn = model_dict.get('milestone')
model_dict['milestone'] = milestn.get('name') if milestn else None
model_dict['project_id'] = milestn.get('project_id') if milestn else None
# t_json_str = json.dumps(t_dict, indent = 4)

return model_dict


class TaskApi(Resource):

def get(self):

excluded_fields = ['followers', 'description', 'attachments', 'content', 'resources', 'modifications', 'lesson_learned']
tasks_db = DB_SESSION.query(flask_tracker.models.Task)
tasks = [frmt_model_obj(t, excluded_fields, include_relationship=1, worktimes=True, milestone=True)
for t in tasks_db]
logging.warning(f'tasks({type(tasks)})')

response = {
"results": tasks
}

response_json = json.dumps(response, indent = 4)

return Response(response_json, mimetype="application/json", status=200)


class ProjectApi(Resource):

def get(self):

projects_db = DB_SESSION.query(flask_tracker.models.Project)
projects = [frmt_model_obj(p, [])
for p in projects_db]
logging.warning(f'projects({type(projects)})')

response = {
"results": projects
}

response_json = json.dumps(response, indent = 4)

return Response(response_json, mimetype="application/json", status=200)


def init_restless_api(app, db):

# creating APIs using flask_restful library
_api = Api(app)

global DB_SESSION # pylint: disable=global-statement
if DB_SESSION is None:
DB_SESSION = db.session

_api.add_resource(TaskApi, URL_PREFIX + 'task')
_api.add_resource(ProjectApi, URL_PREFIX + 'project')
15 changes: 14 additions & 1 deletion src/flask_tracker/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from flask import Flask # pylint: disable=import-error

from flask_tracker.models import (init_orm, get_package_version)

from flask_tracker.api import init_restless_api
from flask_tracker.admin import init_admin

from flask_tracker.email_client import EMailClient
Expand Down Expand Up @@ -69,12 +69,25 @@ def _init_app(argv):
db = init_orm(app)
init_admin(app, db)


flask_migrate_ = flask_migrate.Migrate(compare_type=True)
flask_migrate_.init_app(app, db, render_as_batch=True)

wiki_blueprint.template_folder = os.path.join(HERE, 'wiki', 'templates')
app.register_blueprint(wiki_blueprint, url_prefix='/wiki')

app.app_context().push()

# cls_models = [mapper.class_ for mapper in db.Model.registry.mappers]
# for mapper in db.Model.registry.mappers:
# logging.warning(mapper.__dict__)

init_restless_api(app, db)

# for r in app.url_map.iter_rules():
# if 'api' in r.rule:
# logging.warning(f'{r.endpoint}: ({r.rule}, {list(r.methods)})')

return app


Expand Down
61 changes: 48 additions & 13 deletions src/flask_tracker/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -352,19 +352,53 @@ def get_id_short(self):

id_short = property(get_id_short)

def object_to_json(self, indent=2):
data = self.object_to_dict()
return json.dumps(data, indent=indent)

def object_to_dict(self):

data = {c.key: getattr(self, c.key)
for c in inspect(self).mapper.column_attrs}
# ~ for c in inspect(self).mapper.column_attrs if getattr(self, c.key) is not None}

for k in data.keys():
if isinstance(data[k], datetime):
data[k] = data[k].isoformat()
def object_to_json(self, indent=2, include_relationship=0, excluded_fields=None):
data = self.object_to_dict(
include_relationship=include_relationship,
excluded_fields=excluded_fields)
return json.dumps(data, indent=indent, default=str)

def object_to_dict(self, include_relationship=0, excluded_fields=None):

# data = {c.key: getattr(self, c.key)
# for c in inspect(self).mapper.column_attrs}
# # ~ for c in inspect(self).mapper.column_attrs if getattr(self, c.key) is not None}

# for k in data.keys():
# if isinstance(data[k], datetime):
# data[k] = data[k].isoformat()

# return data
if excluded_fields is None:
excluded_fields = []

data = {'type': self.__tablename__}
c_keys = set(inspect(self).mapper.columns.keys())
for c_key in c_keys:
# logging.warning(f'c_key >> {c_key}')
if c_key in excluded_fields:
continue
value = getattr(self, c_key)
if isinstance(value, datetime):
data[c_key] = value.isoformat()
else:
data[c_key] = value

if include_relationship:
r_keys = set(inspect(self).mapper.relationships.keys())
for r_key in r_keys:
# logging.warning(f'r_key >> {r_key}')
if r_key in excluded_fields:
continue
value = getattr(self, r_key)
if isinstance(value, list):
data[r_key] = []
for i in value:
if include_relationship == 1:
data[r_key].append(i.object_to_dict())
if isinstance(value, BaseModel):
if include_relationship == 1:
data[r_key] = value.object_to_dict()

return data

Expand Down Expand Up @@ -763,6 +797,7 @@ def init_orm(app):
# ~ History.__table__.drop(db.engine)
db.create_all()
db.session.commit()
logging.warning('create_all !!!')

install_listeners()

Expand Down
13 changes: 13 additions & 0 deletions src/flask_tracker/static/chart.min.js

Large diffs are not rendered by default.

88 changes: 88 additions & 0 deletions src/flask_tracker/static/reports.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*.tab {
overflow: hidden;
border: 1px solid #ccc;
background-color: #f1f1f1;
}
.tab button {
background-color: inherit;
float: left;
border: none;
outline: none;
cursor: pointer;
padding: 14px 16px;
transition: 0.3s;
}
.tab button:hover {
background-color: #ddd;
}
.tab button.active {
background-color: #ccc;
}
.tabcontent {
display: none;
padding: 6px 12px;
border: 1px solid #ccc;
border-top: none;
height: 90vh;
}*/

/* TABLE CSS*/

#table-status-tasks{
margin-top: 20px;
}

.table-status-tasks-td{
border: 3px solid #dddddd;
text-align: left;
padding: 8px;
}

/* SIDE NAV */
.sidenav {
height: 100%;
width: 160px;
position: fixed;
z-index: 1;
top: 0;
left: 0;
background-color: #111;
overflow-x: hidden;
padding-top: 20px;
}

.sidenav a {
padding: 6px 8px 6px 16px;
text-decoration: none;
font-size: 25px;
color: #818181;
display: block;
}

.sidenav a:hover {
color: #f1f1f1;
}



.flex-container {
display: flex;
flex-wrap: wrap;
margin-left: 165px;
width: 70%
}

#filters {
margin-top: 35px;
margin-left: 165px;
display: none;
/*display: inline-block;*/
}

.filters_btn {
display: inline-block;
}
Loading

0 comments on commit 578d57f

Please sign in to comment.