Skip to content

Commit

Permalink
#90 - Project page working
Browse files Browse the repository at this point in the history
  • Loading branch information
Philipp Kraft committed Nov 27, 2023
1 parent f955fd2 commit 83d465e
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 79 deletions.
5 changes: 3 additions & 2 deletions odmf/db/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,16 +137,17 @@ class ObjectGetter:
>>> print(ds[10])
>>> ds.q.filter_by(measured_by='philipp')
"""
def __init__(self, cls: type, session: orm.Session):
def __init__(self, cls: type, session: orm.Session, **filter):
self.cls = cls
self.session = session
self.filter = filter

def __repr__(self):
return f'db.{self.cls.__name__}[...]'

@property
def q(self) -> orm.Query:
return self.session.query(self.cls)
return self.session.query(self.cls).filter_by(**self.filter)

def __getitem__(self, item):
return self.q.get(item)
Expand Down
2 changes: 1 addition & 1 deletion odmf/db/person.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def projects(self):
for pm in (
self.session().query(ProjectMember)
.filter(ProjectMember.member == self)
.order_by(ProjectMember.access_level.desc(), ProjectMember._person)
.order_by(ProjectMember.access_level.desc(), ProjectMember._member)
):
yield pm.project, pm.access_level

Expand Down
9 changes: 6 additions & 3 deletions odmf/db/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ class Project(Base):
)
name = sql.Column(sql.String)
comment = sql.Column(sql.String)
directory = sql.Column(sql.String)
sourcelink = sql.Column(sql.String)
organization = sql.Column(sql.String, default='uni-giessen.de')
datasets = sql.orm.relationship('Dataset')

@property
Expand All @@ -35,14 +36,16 @@ def members_query(self):
def members(self, access_level=0):
for pm in (
self.members_query.filter(ProjectMember.access_level>=access_level)
.order_by(ProjectMember.access_level.desc(), ProjectMember._person)
.order_by(ProjectMember.access_level.desc(), ProjectMember._member)
):
yield pm.member, pm.access_level

def add_member(self, person: Person|str, access_level: int=0):
if pm:=self[person]:
pm.access_level = access_level
else:
if not type(person) is Person:
person = Person.get(self.session(), person)
pm = ProjectMember(member=person, project=self, access_level=access_level)
self.session().add(pm)
return pm
Expand Down Expand Up @@ -108,7 +111,7 @@ class ProjectMember(Base):
__tablename__ = 'project_member'

_project = sql.Column('project', sql.ForeignKey('project.id', ondelete='CASCADE'), primary_key=True)
_person = sql.Column('person', sql.ForeignKey('person.username', ondelete='CASCADE'), primary_key=True)
_member = sql.Column('member', sql.ForeignKey('person.username', ondelete='CASCADE'), primary_key=True)

project = sql.orm.relationship('Project')
member = sql.orm.relationship('Person')
Expand Down
2 changes: 2 additions & 0 deletions odmf/db/sql/migration/2023-11-project-authorization.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
alter table project add column organization varchar default 'uni-giessen.de';
alter table project add column sourcelink varchar;
62 changes: 38 additions & 24 deletions odmf/static/templates/project.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
<!-- insert additional scripts -->
<script type="text/javascript">
$(() =>{
$
});
</script>
</py:block>
Expand All @@ -32,14 +31,21 @@
</py:block>
<py:block name="content">
<div class="container m-0 p-0">
<div id="error-row" class="row mt-2 w-100 d-none">
<div id="error-row" class="row mt-2 w-100 ${'' if error else 'd-none'}">
<div class="container">
<div class="row bg-danger text-white border rounded p-4">
<h1 class="display-3 col-lg-2">Error</h1>
<div class="lead col-lg-10" id="error" py:content="markdown(error)"/>
</div>
</div>
</div>
<div id="msg-row" class="row mt-2 w-100 ${'' if msg else 'd-none'}">
<div class="container">
<div class="row bg-success text-white border rounded p-4">
<div class="lead col-lg-10" id="msg" py:content="markdown(msg)"/>
</div>
</div>
</div>
<div class="container" py:if="actproject">
<div id="description" py:if="actproject">
<div class="row mt-2 w-100">
Expand All @@ -53,12 +59,15 @@ <h2 class="display-4 mr-8" py:content="f'{actproject.name}'"/>
</div>
<div class="row">
<div class="col-lg-10">
<div class="container border-bottom" py:if="actproject.directory">
<a href="${f'{conf.root_url}/{actproject.directory}'}">
<div class="container border-bottom">
<a href="${actproject.sourcelink}">
<i class="fas fa-link mr-2"/>${actproject.name} homepage
</a>
by
<span class="badge badge-primary ml-2" py:content="actproject.organization"/>

</div>
<div class="container" py:with="p=actproject.person_responsible" py:content="markdown('Spokes person: user:' + p.username)"/>
<div class="container" py:with="p=actproject.person_responsible" py:content="markdown('Spokes person: user:' + (p.username if p else 'N/A'))"/>
<div class="container" py:content="markdown(actproject.comment)"/>
</div>
<div class="col-lg-2">
Expand All @@ -75,21 +84,21 @@ <h2 class="display-4 mr-8" py:content="f'{actproject.name}'"/>

</div>
<div id="edit" class="container collapse border rounded px-4">
<form action="${conf.root_url}/project/save"
<form action="save"
method="post" py:if="is_member('supervisor')"
>
<div class="form-row mt-2">
<div class="form-group">
<label for="">ID:</label>
<input type="text" id="id" name="id" class="form-control" value="${actproject.id}"
<input type="text" id="id" xname="id" class="form-control" value="${actproject.id}"
readonly="readonly"/>
</div>
<div class="form-group">
<label for="">Name:</label>
<input type="text" id="name" name="name" class="form-control" value="${actproject.name}"/>
</div>
</div>
<!--<div class="form-row">
<div class="form-row">
<div class="form-group">
<label for="sourcelink">Link to project homepage</label>
<input type="text" id="sourcelink" name="sourcelink" class="form-control"
Expand All @@ -100,12 +109,12 @@ <h2 class="display-4 mr-8" py:content="f'{actproject.name}'"/>
<input type="text" id="organization" name="organization" class="form-control"
value="${actproject.organization}"/>
</div>
</div>-->
</div>
<div class="form-row">
<div class="form-group">
<label for="responsible">Spokes person</label>
<select id="responsible" name="person_responsible" class="form-control">
<option value="p.username" py:content="p" py:for="p in supervisors" py:attrs="markoption(p.username == actproject.person_responsible.username)"/>
<select id="responsible" name="person" class="form-control">
<option value="${p.username}" py:content="p" py:for="p in supervisors" py:attrs="markoption(p == actproject.person_responsible)"/>
</select>
</div>
</div>
Expand All @@ -116,7 +125,7 @@ <h2 class="display-4 mr-8" py:content="f'{actproject.name}'"/>
rows="4"
py:content="actproject.comment"/>
</div>
<button class="btn btn-success mb-2" type="submit" id="save" name="save">
<button class="btn btn-success mb-2" type="submit" id="save">
<i class="fas fa-save mr-2"/>
save changes
</button>
Expand All @@ -130,28 +139,33 @@ <h2 class="border-bottom">Members</h2>
<span py:content="member" class="ml-2"/>(<span py:content="level"/>)

</div>
<button data-member="${member.username}"
py:if="is_member('admin')"
class="btn btn-outline-danger btn-sm px-1 my-0 py-0 col-sm-1 px-4 project-remove-member"
title="remove" data-toggle="tooltip"
><i class="fas fa-times"/></button>
<form method="post" action="remove_member">
<button data-member="${member.username}"
py:if="is_member('admin')"
type="submit"
class="btn btn-danger btn-sm col-sm-1 pr-3 project-remove-member"
name="member_name" value="${member.username}"
title="remove" data-toggle="tooltip"
><i class="fas fa-times"/></button>

</form>
</li>
</ul>
<a href="#add-member" class="btn-sm btn-primary dropdown-toggle" data-toggle="collapse" aria-controls="add-member" aria-role="button"><i class="fas fa-plus"/> add member...</a>
<div py:if="is_member('admin')" class="form-row collapse" id="add-member">
<form class="container border" method="post" action="${odmf_ref}/project/add_member">
<input type="hidden" value="${actproject.id}"/>
<a href="#add-member" py:if="is_member('admin')" class="btn-sm btn-primary dropdown-toggle" data-toggle="collapse" aria-controls="add-member" aria-role="button"><i class="fas fa-plus"/> add member...</a>
<div py:if="is_member('admin')" class="collapse" id="add-member">
<form class="form-row border" method="post" action="add_member">
<input type="hidden" value="${actproject.id}" xname="project_id"/>
<select id="add_who" class="form-control col-sm" name="member_name">
<option value="p.username" py:for="p in persons" py:content="p"/>
<option value="${p.username}" py:for="p in persons" py:content="p"/>
</select>
<select id="add_level" class="form-control col-sm-3" name="access_level">
<option value="1">Logger</option>
<option value="2">Editor</option>
<option value="3">Supervisor</option>
<option value="4">Admin</option>
</select>
<input type="submit" py:if="is_member('admin')" id="addmember"
class="btn btn-success btn-sm col-sm-1 project-add-member"/>
<button type="submit" id="addmember"
class="btn btn-success btn-sm col-sm-1 project-add-member"><i class="fas fa-check"/></button>
</form>
</div>

Expand Down
90 changes: 41 additions & 49 deletions odmf/webpage/db_editor/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@
from ... import db
from ...config import conf

@cherrypy.popargs('project_id')
@web.show_in_nav_for(1, 'user-friends')
class ProjectPage:

@expose_for(group.logger)
def default(self, project_id=None, error=None):
def index(self, project_id=None, error=None, msg=None):

with db.session_scope() as session:
projects = db.ObjectGetter(db.Project, session)
Expand All @@ -29,67 +30,58 @@ def default(self, project_id=None, error=None):
projects=projects.q.order_by(db.Project.id),
actproject=project_from_id,
supervisors=supervisors,
persons=persons, error=error) \
persons=persons, error=error, msg=msg) \
.render()


@expose_for(group.supervisor)
@web.method.post
def save(self, **kwargs):

name = kwargs.get('name')
person = kwargs.get('person')
comment = kwargs.get('comment')
project_id = int(kwargs.get('id', 0))

with db.session_scope() as session:
if project_id:
project = db.Project.get(project_id)
else:
project = db.Project()
session.add(project)

person = session.query(db.Person).get(person)
project.name = name
project.comment = comment
if person is None:
raise RuntimeError('Spokesperson not found')
def save(self, project_id:str, name:str, person:str, comment: str, sourcelink: str, organization: str):
error = ''

project_id = int(project_id)
try:
with db.session_scope() as session:
if project_id:
project = db.Project.get(session, project_id)
else:
project = db.Project()
session.add(project)

person = session.query(db.Person).get(person)
project.name = name
project.comment = comment
project.sourcelink = sourcelink
project.organization = organization
if person is None:
raise RuntimeError('Spokesperson not found')
except RuntimeError as e:
error = f'Save failed: {e}'
raise web.redirect(f'/{conf.root_url}project/{project_id}', error=error, msg=f'{name} updated' if not error else None)


@expose_for(group.supervisor)
@web.method.post
def add_member(self, project_id, member_name, access_level):
with db.session_scope() as session:
project = db.Project.get(session, project_id)
project.add_member(member_name, access_level)
error = None
try:
with db.session_scope() as session:
project = db.Project.get(session, project_id)
project.add_member(member_name, int(access_level))
except RuntimeError as e:
error = f'Save failed: {e}'
raise web.redirect(f'/{conf.root_url}project/{project_id}', error=error, msg=f'{member_name} added' if not error else None)

@expose_for(group.supervisor)
@web.method.post
def remove_member(self, project_id, member_name):
with db.session_scope() as session:
project = db.Project.get(session, project_id)
project.remove_member(member_name)





@expose_for(group.supervisor)
def delete(self, project_id=None, force=None):

with db.session_scope() as session:

if str(force) == 'True':

project = session.query(db.Project).get(project_id)
session.delete(project)
# Returning to project
raise web.redirect(conf.root_url + '/project')

else:
project = session.query(db.Project).get(project_id)
error = ''
return web.render('project_delete.html', project=project,
error=error).render()
error = None
try:
with db.session_scope() as session:
project = db.Project.get(session, project_id)
project.remove_member(member_name)
except RuntimeError as e:
error = f'Save failed: {e}'
raise web.redirect(f'/{conf.root_url}project/{project_id}', error=error, msg=f'{member_name} removed' if not error else None)


0 comments on commit 83d465e

Please sign in to comment.