Compare commits

...

14 Commits

Author SHA1 Message Date
f5f1fa721b Tilføj seneste bedsked dato til threads 2022-06-02 12:21:41 +02:00
3ab1c58c14 Merge branch 'remove_orm' into ting 2022-06-02 11:30:28 +02:00
66ef5e9e25 Design ting 2022-06-02 11:30:04 +02:00
14343422d3 Slet orm halløj 2022-06-02 11:21:54 +02:00
9d02b2529a Tilføj group_exist, ændre insert_group i models.py
insert_group returnere den tilføjet gruppe. Så man kan tilføje brugeren til den nyoprettet gruppe
2022-06-02 09:23:32 +02:00
dfc925d5c2 Fix for #1 2022-06-01 11:18:54 +02:00
5f95d59f2e Bruger info dump 2022-05-31 17:59:31 +02:00
5c76f8f9be Update __int__.py 2022-05-31 17:44:08 +02:00
abf12212f5 Slettet unødvendige filer 2022-05-31 17:42:15 +02:00
3e1fa025cc tilføj til-/afmelding af grupper 2022-05-31 17:37:45 +02:00
674c8741e7 Ændre felt hidden til mandatory.
En gruppe kan være obligatorisk. Som man hverkan tilmelde sig eller forlade.
2022-05-31 16:54:37 +02:00
5ecfe3b836 Fiks opslags rækkefølge og dato format 2022-05-31 16:44:25 +02:00
b21a9c71a1 Tilføj tjek af gruppe navn dupletter 2022-05-31 16:40:38 +02:00
4592591c4e Tilføj oprettelse af tråde, grupper og opslag 2022-05-31 16:21:09 +02:00
20 changed files with 378 additions and 434 deletions

View File

@ -1,6 +1,7 @@
from flask import render_template, Blueprint
from flask import render_template, Blueprint, flash, redirect
from flask_login import current_user, login_required
from aula.models import get_group
from aula.models import get_group, insert_group, group_exist
from aula.forms import CreateThreadForm, CreateGroupForm, CreatePostForm
Group = Blueprint('Group', __name__)
@ -8,15 +9,50 @@ Group = Blueprint('Group', __name__)
@login_required
def groups():
groups = current_user.get_groups_joinable()
return render_template('groups.html', groups=groups)
form = CreateGroupForm()
return render_template('groups.html', groups=groups, form=form)
@Group.route("/group/<int:group_id>", methods=['GET'])
@Group.route("/groups/<int:group_id>", methods=['GET'])
@login_required
def show(group_id):
group = get_group(group_id)
posts = group.get_posts()
threads = group.get_threads()
form = CreateThreadForm()
formpost = CreatePostForm()
if (group is not None):
return render_template('group_show.html', group=group, posts=posts)
return render_template('group_show.html', group=group, posts=posts, threads=threads, form=form, formpost=formpost)
else:
return f"Der findes ikke en gruppe med id {group_id}."
@Group.route("/groups/create", methods=['POST'])
@login_required
def create():
form = CreateGroupForm()
# Make sure we dont try to create group with same name as others
# Since name has UNIQUE constraint.
if group_exist(form.title.data):
flash('En gruppe med det navn findes allerede', 'danger')
return redirect(f"/groups")
group = insert_group(form.title.data, form.mandatory.data)
current_user.join_group(group.group_id)
flash('Gruppen blev oprettet', 'success')
return redirect(f"/groups")
@Group.route("/groups/join/<int:group_id>", methods=['GET'])
def join(group_id):
group = get_group(group_id)
current_user.join_group(group_id)
flash(f'Du er nu tilmeldt {group.name} gruppen', 'success')
return redirect(f"/groups/{group_id}")
@Group.route("/groups/leave/<int:group_id>", methods=['GET'])
def leave(group_id):
group = get_group(group_id)
current_user.leave_group(group_id)
flash(f'Du er frameldt {group.name} gruppen', 'success')
return redirect(f"/groups")

14
aula/Post/routes.py Normal file
View File

@ -0,0 +1,14 @@
from flask import render_template, Blueprint, flash, redirect
from flask_login import current_user, login_required
from aula.models import insert_post
from aula.forms import CreatePostForm
Post = Blueprint('Post', __name__)
@Post.route("/posts/create", methods=['POST'])
@login_required
def create():
form = CreatePostForm()
insert_post(form.group_id.data, form.author_id.data, form.title.data, form.content.data)
flash('Opslag blev oprettet', 'success')
return redirect(f"/groups/{form.group_id.data}")

View File

@ -1,7 +1,7 @@
from flask import redirect, render_template, Blueprint
from flask import redirect, render_template, Blueprint, flash
from flask_login import login_required, current_user
from aula.models import get_thread, insert_message
from aula.forms import SendMessageForm
from aula.models import get_thread, insert_message, insert_thread
from aula.forms import SendMessageForm, CreateThreadForm
Threads = Blueprint('Threads', __name__)
@ -17,7 +17,7 @@ def show(thread_id):
thread = get_thread(thread_id)
if thread is None:
return f"Der findes ikke en tråd med id {thread_id}."
elif not current_user.in_thread(thread_id):
elif not current_user.is_member_of_group(thread.group_id):
return f"Du har ikke adgang til tråden med id {thread_id}."
else:
form = SendMessageForm()
@ -27,3 +27,12 @@ def show(thread_id):
return redirect(f"/threads/{thread_id}")
return render_template("thread_show.html", thread=thread, messages=thread.get_messages(), form=form)
@Threads.route("/threads/create", methods=['POST'])
@login_required
def create():
form = CreateThreadForm()
insert_thread(form.group_id.data, form.title.data)
flash('Tråden blev oprettet', 'success')
return redirect(f"/groups/{form.group_id.data}")

View File

@ -17,9 +17,11 @@ login_manager.login_message_category = 'info'
from aula.Login.routes import Login
from aula.Group.routes import Group
from aula.Threads.routes import Threads
from aula.Post.routes import Post
app.register_blueprint(Login)
app.register_blueprint(Group)
app.register_blueprint(Threads)
app.register_blueprint(Post)
#from bank import routes

View File

@ -1,5 +1,5 @@
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField, BooleanField
from wtforms import StringField, PasswordField, SubmitField, BooleanField, HiddenField
from wtforms.validators import DataRequired, Length
class AddUserForm(FlaskForm):
@ -19,3 +19,21 @@ class UserLoginForm(FlaskForm):
class SendMessageForm(FlaskForm):
besked = StringField('Besked', validators=[DataRequired()])
submit = SubmitField('Send')
class CreateThreadForm(FlaskForm):
group_id = HiddenField('GroupID', validators=[DataRequired()])
title = StringField('Title', validators=[DataRequired()])
submit = SubmitField()
class CreateGroupForm(FlaskForm):
title = StringField('Title', validators=[DataRequired()])
mandatory = BooleanField('Obligatorisk gruppe')
submit = SubmitField("Opret gruppe")
class CreatePostForm(FlaskForm):
title = StringField('Title', validators=[DataRequired()])
content = StringField('Indhold', validators=[DataRequired()])
author_id = HiddenField('AuthorID', validators=[DataRequired()])
group_id = HiddenField('GroupID', validators=[DataRequired()])
submit = SubmitField("Opret opslag")

View File

@ -25,14 +25,17 @@ class Group(tuple):
def __init__(self, group_data):
self.group_id = group_data[0]
self.name = group_data[1]
self.hidden = group_data[2]
self.mandatory = group_data[2]
super().__init__()
def get_posts(self):
cur = conn.cursor()
sql_call = """
SELECT * FROM posts
WHERE group_id = %s
SELECT post_id, title, content, created_date, g.group_id, g.name, g.mandatory, u.user_id, u.first_name, u.last_name, u.email, u.address, u.role FROM posts as p
INNER JOIN groups g on g.group_id = p.group_id
INNER JOIN users u on u.user_id = p.author_id
WHERE p.group_id = %s
ORDER BY created_date DESC;
"""
cur.execute(sql_call, (self.group_id,))
Posts = cur.fetchall()
@ -45,7 +48,8 @@ class Group(tuple):
def get_threads(self):
cur = conn.cursor()
sql_call = """
SELECT * FROM threads
SELECT thread_id, title, g.group_id, g.name, g.mandatory FROM threads
INNER JOIN groups g on g.group_id = threads.group_id
WHERE threads.group_id = %s
"""
cur.execute(sql_call, (self.group_id,))
@ -61,20 +65,15 @@ class Message(tuple):
self.message_id = message_data[0]
self.content = message_data[1]
self.thread_id = message_data[2]
self.author_id = message_data[3]
self.author = None
self._created_date = message_data[4]
self._get_author()
self._created_date = message_data[3]
self.author = {
"user_id": message_data[4],
"first_name": message_data[5],
"last_name": message_data[6],
"role": message_data[7],
}
super().__init__()
def _get_author(self):
cur = conn.cursor()
sql_call = """
SELECT * FROM users WHERE user_id = %s
"""
cur.execute(sql_call, (self.author_id,))
self.author = User(cur.fetchone())
@property
def created_date(self):
now = datetime.now()
@ -101,46 +100,44 @@ class Message(tuple):
class Post(tuple):
def __init__(self, post_data):
self.post_id = post_data[0]
self.group_id = post_data[1]
self.group = None
self.author_id = post_data[2]
self.author = None
self.title = post_data[3]
self.content = post_data[4]
self.created_date = post_data[5]
self._get_group()
self._get_author()
self.title = post_data[1]
self.content = post_data[2]
self.created_date = post_data[3]
self.group = {
'group_id': post_data[4],
'name': post_data[5],
'mandatory': post_data[6],
}
self.author = {
'user_id': post_data[7],
'first_name': post_data[8],
'last_name': post_data[9],
'email': post_data[10],
'address': post_data[11],
'role': post_data[12],
}
super().__init__()
def _get_author(self):
cur = conn.cursor()
sql_call = """
SELECT * FROM users WHERE user_id = %s
"""
cur.execute(sql_call, (self.author_id,))
self.author = User(cur.fetchone())
def _get_group(self):
cur = conn.cursor()
sql_call = """
SELECT * FROM groups WHERE group_id = %s
"""
cur.execute(sql_call, (self.group_id,))
self.group = Group(cur.fetchone())
class Thread(tuple):
def __init__(self, thread_data):
self.thread_id = thread_data[0]
self.title = thread_data[1]
self.group = {
"group_id": thread_data[2],
"name": thread_data[3],
"mandatory": thread_data[4]
}
self.group_id = thread_data[2]
if len(thread_data) == 6:
self.last_message_date = thread_data[5]
super().__init__()
def get_messages(self):
cur = conn.cursor()
sql_call = """
SELECT * FROM messages
WHERE thread_id = %s
ORDER BY created_date ASC
SELECT message_id, content, thread_id, created_date ,u.user_id, u.first_name, u.last_name, u.role FROM messages
INNER JOIN users u on u.user_id = messages.author_id
WHERE messages.thread_id = %s;
"""
cur.execute(sql_call, (self.thread_id,))
messages = cur.fetchall()
@ -193,8 +190,8 @@ class User(tuple, UserMixin):
sql_call = """
SELECT groups.* FROM groups INNER JOIN users_groups ON groups.group_id = users_groups.group_id WHERE users_groups.user_id = %s
UNION
SELECT groups.* FROM groups WHERE groups.hidden = TRUE
ORDER BY hidden ASC, name DESC
SELECT groups.* FROM groups WHERE groups.mandatory = FALSE
ORDER BY mandatory ASC, name DESC
"""
cur.execute(sql_call, (self.user_id,))
groups = cur.fetchall()
@ -226,11 +223,19 @@ class User(tuple, UserMixin):
def get_threads(self):
cur = conn.cursor()
sql_call = """
SELECT * FROM threads WHERE thread_id IN
(
SELECT thread_id FROM users_threads
WHERE user_id = %s
)
SELECT threads.thread_id, title, g.group_id, g.name, g.mandatory, lm.last_message_date FROM threads
INNER JOIN
groups g
ON g.group_id = threads.group_id
LEFT JOIN
(SELECT thread_id, MAX(created_date) as last_message_date FROM messages GROUP BY thread_id) lm
ON threads.thread_id = lm.thread_id
WHERE g.group_id IN
(
SELECT group_id FROM users_groups
WHERE user_id = %s
)
ORDER BY last_message_date DESC NULLS LAST;
"""
cur.execute(sql_call, (self.user_id,))
threads = cur.fetchall()
@ -250,8 +255,6 @@ class User(tuple, UserMixin):
cur.execute(sql_call, (self.user_id, thread_id))
return cur.rowcount > 0
def insert_users(user_id, first_name, last_name, password, email, adresse, role):
cur = conn.cursor()
sql_call = """
@ -288,11 +291,14 @@ def select_users_by_email(email):
def get_posts_for_user(user_id):
cur = conn.cursor()
sql_call = """
SELECT * FROM posts
WHERE group_id in (
SELECT group_id FROM users_groups
SELECT post_id, title, content, created_date, g.group_id, g.name, g.mandatory, u.user_id, u.first_name, u.last_name, u.email, u.address, u.role FROM posts as p
INNER JOIN groups g on g.group_id = p.group_id
INNER JOIN users u on u.user_id = p.author_id
WHERE g.group_id in (
SELECT g.group_id FROM users_groups
WHERE user_id = %s
)
ORDER BY created_date DESC
"""
cur.execute(sql_call, (user_id,))
user = [Post(i) for i in cur.fetchmany(50)] if cur.rowcount > 0 else []
@ -313,7 +319,8 @@ def get_group(group_id):
def get_thread(thread_id):
cur = conn.cursor()
sql = """
SELECT * FROM threads
SELECT thread_id, title, g.group_id, g.name, g.mandatory FROM threads
INNER JOIN groups g on g.group_id = threads.group_id
WHERE thread_id = %s
"""
cur.execute(sql, (thread_id,))
@ -321,6 +328,45 @@ def get_thread(thread_id):
cur.close()
return thread
def insert_thread(group_id, title):
cur = conn.cursor()
sql = """
INSERT INTO threads(group_id, title) VALUES (%s, %s)
"""
cur.execute(sql, (group_id, title))
conn.commit()
cur.close()
def group_exist(name):
cur = conn.cursor()
sql = """
SELECT COUNT(*) FROM groups WHERE name = %s
"""
cur.execute(sql, (name,))
return cur.fetchone()[0] > 0
def insert_group(name, mandatory):
cur = conn.cursor()
sql = """
INSERT INTO groups(name, mandatory) VALUES (%s, %s) RETURNING *
"""
cur.execute(sql, (name, mandatory))
result = Group(cur.fetchone()) if cur.rowcount > 0 else None
conn.commit()
cur.close()
return result
def insert_post(group_id, author_id, title, content):
cur = conn.cursor()
sql = """
INSERT INTO posts(group_id, author_id, title, content) VALUES (%s, %s, %s, %s)
"""
cur.execute(sql, (group_id, author_id, title, content))
conn.commit()
cur.close()
def insert_message(content, thread_id, author_id):
cur = conn.cursor()
sql_call = """

View File

@ -13,7 +13,7 @@ CREATE TABLE IF NOT EXISTS users (
CREATE TABLE IF NOT EXISTS groups (
group_id SERIAL PRIMARY KEY,
name varchar(64) NOT NULL UNIQUE,
hidden boolean DEFAULT TRUE
mandatory boolean DEFAULT TRUE
);
CREATE TABLE IF NOT EXISTS threads (

View File

@ -8,7 +8,7 @@ INSERT INTO public.users(user_id, first_name, last_name, password, email, addres
(5004,'Phoebe', 'Buffay', '$2b$12$KFkp1IEMGT4QrWwjPGhE3ejOv6Z3pYhx/S4qOoFbanR2sMiZqgeJO', 'phoebe@test.dk', 'Central Perk', 'parent'),
(5005,'Ross', 'Geller', '$2b$12$KFkp1IEMGT4QrWwjPGhE3ejOv6Z3pYhx/S4qOoFbanR2sMiZqgeJO', 'ross@test.dk', 'Central Perk', 'student');
INSERT INTO public.groups(group_id, name, hidden) VALUES
INSERT INTO public.groups(group_id, name, mandatory) VALUES
(1000, 'fodbold', TRUE),
(1001,'3a', FALSE);
@ -19,8 +19,8 @@ INSERT INTO threads(thread_id ,title, group_id) VALUES
INSERT INTO messages (content, thread_id, author_id, created_date) VALUES
('Eleverne har ondt i fødderne når de spiller fodbild. Hvem kender et godt skomærke?', 2000, 5000, NOW() - INTERVAL '3.189 day'),
('Jeg tror min søn har nogle han er glad for. Jeg spørger ham lige 😀', 2000, 5002, NOW() - INTERVAL '2.951 day'),
('Tak 👍', 2000, 5000, NOW() - INTERVAL '1.894 day'),
('Jeg tror min søn har nogle han er glad for. Jeg spørger ham lige', 2000, 5002, NOW() - INTERVAL '2.951 day'),
('Tak', 2000, 5000, NOW() - INTERVAL '1.894 day'),
('Er det meningen vi skal give dem sko med????', 2000, 5001, NOW() - INTERVAL '1.05 hour'),
('Rachel, giver du ikke dine børn sko med til fodbold?', 2000, 5002, NOW() - INTERVAL '0.95 hour'),
('Hvad er der galt med dig?', 2000, 5003, NOW() - INTERVAL '0.94 hour'),

View File

@ -1,4 +1,78 @@
{% extends "layout.html" %}
{% block content %}
<h1>{{ current_user.name }}</h1>
{% endblock content %}
<h1>Bruger Information</h1>
<table class="table table-striped table-sm">
<thead>
<tr>
<th scope="col">Attribute</th>
<th scope="col">værdi</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">user_id</th>
<td>{{ current_user.user_id }}</td>
</tr>
<tr>
<th scope="row">first_name</th>
<td>{{ current_user.first_name }}</td>
</tr>
<tr>
<th scope="row">last_name</th>
<td>{{ current_user.last_name }}</td>
</tr>
<tr>
<th scope="row">email</th>
<td>{{ current_user.email }}</td>
</tr>
<tr>
<th scope="row">address</th>
<td>{{ current_user.address }}</td>
</tr>
<tr>
<th scope="row">role</th>
<td>{{ current_user.role }}</td>
</tr>
</tbody>
</table>
<p><b>Grupper</b></p>
<table class="table table-striped table-sm">
<thead>
<tr>
<th scope="col">group_id</th>
<th scope="col">name</th>
<th scope="col">mandatory</th>
</tr>
</thead>
<tbody>
{% for group in current_user.get_groups() %}
<tr>
<td><a href="{{ url_for('Group.show', group_id = group.group_id) }}">{{ group.group_id }}</a></td>
<td>{{ group.name }}</td>
<td>{{ group.mandatory }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<p><b>Tråde</b></p>
<table class="table table-striped table-sm">
<thead>
<tr>
<th scope="col">thread_id</th>
<th scope="col">title</th>
<th scope="col">group_id</th>
</tr>
</thead>
<tbody>
{% for thread in current_user.get_threads() %}
<tr>
<td><a href="{{ url_for('Threads.show', thread_id = thread.thread_id) }}">{{ thread.thread_id }}</a></td>
<td>{{ thread.title }}</td>
<td>{{ thread.group_id }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock content %}

View File

@ -1,59 +0,0 @@
{% extends "layout.html" %}
{% block content %}
<div class="content-section">
<form method="POST" action="">
{{ form.hidden_tag() }}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Add a new customer</legend>
<div class="form-group">
{{ form.username.label(class="form-control-label") }}
{% if form.username.errors %}
{{ form.username(class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.username.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.username(class="form-control form-control-lg") }}
{% endif %}
</div>
<div class="form-group">
{{ form.CPR_number.label(class="form-control-label") }}
{% if form.CPR_number.errors %}
{{ form.CPR_number(class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.CPR_number.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.CPR_number(class="form-control form-control-lg") }}
{% endif %}
</div>
<div class="form-group">
{{ form.password.label(class="form-control-label") }}
{% if form.password.errors %}
{{ form.password(class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.password.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.password(class="form-control form-control-lg") }}
{% endif %}
</div>
</fieldset>
<div class="form-group">
{{ form.submit(class="btn btn-outline-info") }}
</div>
</form>
</div>
<div class="border-top pt-3">
<small class="text-muted">
Already Have An Account? <a class="ml-2" href="{{ url_for('Login.login') }}">Sign In</a>
</small>
</div>
{% endblock content %}

View File

@ -1,17 +1,74 @@
{% extends "layout.html" %}
{% block content %}
<h1>{{ group.name }}</h1>
<h1>{{ group.name }}
</h1>
<hr>
{% if posts|length == 0 %}
<p>Gruppen har ingen opslag endnu</p>
{% endif %}
{% for post in posts %}
<article class="media content-section">
<div class="media-body">
<div class="article-metadata">
<a class="mr-2 author-name" href="#">{{ post.author.first_name }} {{ post.author.last_name }}</a>
<small class="text-muted">{{ post.date_posted }}</small>
<a class="mr-2 author-name" href="#">{{ post.author.first_name }} {{ post.author.last_name }} </a>
<small class="text-muted float-right">{{ post.created_date.strftime('%H:%M %d-%m-%Y')}}</small>
</div>
<h2><a class="article-title" href="#">{{ post.title }}</a></h2>
<p class="article-content">{{ post.content }}</p>
</div>
</article>
{% endfor %}
{% if current_user.is_member_of_group(group.group_id) %}
<div class="card">
<div class="card-body">
<p style="font-weight: bold;">Skriv opslag</p>
<form method="POST" action="{{ url_for('Post.create')}}">
{{ formpost.group_id(value=group.group_id) }}
{{ formpost.author_id(value=current_user.user_id) }}
<div class="row">
<div class="col-md-4">{{ formpost.title(class="form-control", placeholder="Title") }}</div>
<div class="col-md-8">{{ formpost.content(class="form-control", placeholder="Indhold") }}</div>
<div class="col-md-12 mt-2">{{ formpost.submit(class="btn btn-primary btn-block btn-sm", value="Opret opslag") }}</div>
</div>
</form>
</div>
</div>
{% endif %}
{% endblock content %}
{% block sidebar %}
{% if current_user.is_member_of_group(group.group_id) %}
<p style="font-weight: bold;">Gruppe tråde</p>
{% if threads|length == 0 %}
<p>Gruppen har ingen tråde endnu</p>
{% endif %}
{% for thread in threads %}
<p><a href="{{ url_for('Threads.show', thread_id = thread.thread_id) }}">{{ thread.title }}</a></p>
{% endfor %}
<hr>
<form method="POST" action="{{ url_for('Threads.create')}}">
{{ form.group_id(value=group.group_id) }}
<p>{{ form.title(class="form-control", placeholder="Trådens title") }}</p>
<p>{{ form.submit(class="btn btn-primary btn-block", value="Start tråd") }}</p>
</form>
{% else %}
<p>Tilmeld dig gruppe for at se gruppe tråde og skrive opslag</p>
<p><a class="btn btn-success btn-sm btn-block" href="{{ url_for('Group.join', group_id = group.group_id) }}">Tilmeld</a></p>
{% endif %}
{% if current_user.is_member_of_group(group.group_id) %}
<p>
<hr>
{% if group.mandatory %}
<a class="btn btn-secondary btn-sm disabled" href="#">Obligatorisk gruppe</a>
{% else %}
<a class="btn btn-danger btn-sm btn-block" href="{{ url_for('Group.leave', group_id = group.group_id) }}">Forlad gruppen</a>
{% endif %}
</p>
{% endif %}
{% endblock sidebar %}

View File

@ -1,14 +1,39 @@
{% extends "layout.html" %}
{% block content %}
<h1>Grupper</h1>
<hr>
{% if groups|length == 0%}
<p>Ikke medlem af nogle grupper</p>
{% else %}
{% for group in groups %}
<div class="card">
<div class="card-body">
<p><a class="group-name" href="{{ url_for('Group.show', group_id = group.group_id) }}">{{ group.name }}</a></p>
<p>
<a class="group-name" href="{{ url_for('Group.show', group_id = group.group_id) }}">{{ group.name }}</a>
{% if not group.mandatory %}
{% if current_user.is_member_of_group(group.group_id) %}
<a class="btn btn-danger btn-sm float-right" href="{{ url_for('Group.leave', group_id = group.group_id) }}">Afmeld</a>
{% else %}
<a class="btn btn-success btn-sm float-right" href="{{ url_for('Group.join', group_id = group.group_id) }}">Tilmeld</a>
{% endif %}
{% else %}
<a class="btn btn-secondary btn-sm float-right" href="#" disabled>Obligatorisk</a>
{% endif %}
</p>
</div>
</div>
{% endfor %}
{% endif %}
{% endblock content %}
{% block sidebar %}
<p style="font-weight: bold;">Opret gruppe</p>
<form method="POST" action="{{ url_for('Group.create')}}">
<p>{{ form.title(class="form-control", placeholder="Gruppens navn") }}</p>
<p>{{ form.mandatory() }} {{ form.mandatory.label(class="form-check-label") }}</p>
<p>{{ form.submit(class="btn btn-primary btn-block") }}</p>
</form>
{% endblock sidebar %}

View File

@ -9,11 +9,11 @@
<div class="media-body">
<div class="article-metadata">
<a class="mr-2 author-name" href="#">{{ post.author.first_name }} {{ post.author.last_name }}</a>
<small class="text-muted">{{ post.date_posted }}</small>
<small class="text-muted float-right">{{ post.created_date.strftime('%H:%M %d-%m-%Y')}}</small>
</div>
<h2><a class="article-title" href="#">{{ post.title }}</a></h2>
<p class="article-content">{{ post.content }}</p>
<a class="group-name" href="{{ url_for('Group.show', group_id = post.group.group_id) }}"">
<a class="group-name" href="{{ url_for('Group.show', group_id = post.group.group_id) }}">
{{ post.group.name }}
</a>
</div>

View File

@ -1,79 +0,0 @@
{% extends "layout_acc.html" %}
{% block content %}
<h1>{{ current_user.name }}</h1>
<div class="content-section">
<p>Investments:</p>
<table class="table table-striped">
<thead>
<tr>
<th scope="col">account_number</th>
<th scope="col">cpr_number</th>
<th scope="col">creation date</th>
</tr>
</thead>
<tbody>
{% for n in inv %}
<tr>
<th scope="row">{{n[0]}}</th>
<td>{{n[1]}}</td>
<td>{{n[2]}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="content-section">
<p>Investment accounts:</p>
<table class="table table-striped">
<thead>
<tr>
<th scope="col">account_number</th>
<th scope="col">cpr_number</th>
<th scope="col">account created</th>
<th scope="col">deposit total (CD)</th>
</tr>
</thead>
<tbody>
{% for n in inv_sums %}
<tr>
<th scope="row">{{n[0]}}</th>
<td>{{n[1]}}</td>
<td>{{n[2]}}</td>
<td>{{n[3]}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="content-section">
<p>Investment certificats of deposit:</p>
<table class="table table-striped">
<thead>
<tr>
<th scope="col">acc</th>
<th scope="col">cd_number</th>
<th scope="col">start_date</th>
<th scope="col">maturity_date</th>
<th scope="col">rate</th>
<th scope="col">amount</th>
</tr>
</thead>
<tbody>
{% for n in inv_cd_list %}
<tr>
<th scope="row">{{n[0]}}</th>
<td>{{n[3]}}</td>
<td>{{n[4]}}</td>
<td>{{n[5]}}</td>
<td>{{n[6]}}</td>
<td>{{n[7]}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock content %}

View File

@ -50,10 +50,21 @@
<main role="main" class="container">
<div class="row">
<div class="col-md-8">
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<div class="alert alert-{{ category }}">
{{ message }}
</div>
{% endfor %}
{% endif %}
{% endwith %}
{% block content %}{% endblock %}
</div>
<div class="col-md-4">
<div class="content-section">
{% block sidebar %}{% endblock %}
</div>
</div>
</div>

View File

@ -1,100 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='main.css') }}">
{% if title %}
<title>UIS Prototype - {{ title }}</title>
{% else %}
<title>UIS Prototype</title>
{% endif %}
</head>
<body>
<header class="site-header">
<nav class="navbar navbar-expand-md navbar-dark bg-steel fixed-top">
<div class="container">
<a class="navbar-brand mr-4" href="/">UIS Prototype</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarToggle" aria-controls="navbarToggle" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarToggle">
<div class="navbar-nav mr-auto">
<a class="nav-item nav-link" href="{{ url_for('Login.home') }}">Home</a>
{% if current_user.is_authenticated %}
<li class="dropdown">
<a href="#" class="nav-item nav-link dropdown-toggle" data-toggle="dropdown">UIS bank<b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a class="nav-item nav-link" href="{{ url_for('Login.account') }}">Account</a></li>
<li><a class="nav-item nav-link" href="{{ url_for('Employee.transfer') }}">Transfer</a></li>
<li class="divider"></li>
<li><a class="nav-item nav-link" href="{{ url_for('Customer.invest') }}">Investments</a></li>
<li class="divider"></li>
<li><a class="nav-item nav-link" href="https://www.pgadmin.org">site pgAdmin</a></li>
<li><a class="nav-item nav-link" href="http://127.0.0.1:58653/browser/ ">pgAdmin4</a></li>
</ul>
</li>
{% else %}
{% endif %}
<a class="nav-item nav-link" href="{{ url_for('Login.about') }}">About</a>
</div>
<!-- Navbar Right Side -->
<div class="navbar-nav">
{% if current_user.is_authenticated %}
<a class="nav-item nav-link" href="{{ url_for('Login.account') }}">Account</a>
<a class="nav-item nav-link" href="{{ url_for('Employee.transfer') }}">Transfer</a>
<a class="nav-item nav-link" href="{{ url_for('Customer.invest') }}">Investments</a>
<a class="nav-item nav-link" href="{{ url_for('Login.logout') }}">Logout</a>
{% else %}
<a class="nav-item nav-link" href="{{ url_for('Login.login') }}">Login</a>
<a class="nav-item nav-link" href="{{ url_for('Employee.addcustomer') }}">Register</a>
{% endif %}
</div>
</div>
</div>
</nav>
</header>
<main role="main" class="container">
<div class="row">
<div class="col-md-8">
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<div class="alert alert-{{ category }}">
{{ message }}
</div>
{% endfor %}
{% endif %}
{% endwith %}
{% block content %}{% endblock %}
</div>
<div class="col-md-4">
<div class="content-section">
<h3>Account</h3>
<ul class="list-group">
<li class="list-group-item list-group-item-light"><a class="nav-item nav-link" href="{{ url_for('Employee.transfer') }}">Transfer</a></li>
<li class="list-group-item list-group-item-light">Checking Accounts</li>
<li class="list-group-item list-group-item-light">Investment Accounts</li>
<li class="list-group-item list-group-item-light"><a class="nav-item nav-link" href="{{ url_for('Customer.invest') }}">View investment accounts</a></li>
<li class="list-group-item list-group-item-light">etc</li>
</ul>
</p>
</div>
</div>
</div>
</main>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
</body>
</html>

View File

@ -1,70 +0,0 @@
{% extends "layout.html" %}
{% block content %}
<h1>Test Page</h1>
<p>Dette er en testside. Hej med dig. <b>fed tekst,</b> <i>kursiv tekst</i> </p>
<p><b>fed tekst, <i>fed og kursiv tekst</i></b></p>
<p>Liste af ansatte:</p>
<ul>
{% for e in emp %}
<li>{{ e[1] }}</li>
{% endfor %}
</ul>
<form method="POST" action="">
{{ form.hidden_tag() }}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Add a new employee</legend>
<!-- Id-felt -->
<div class="form-group">
{{ form.id.label(class="form-control-label") }}
{% if form.id.errors %}
{{ form.id(class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.id.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.id(class="form-control form-control-lg") }}
{% endif %}
</div>
<!-- Username-felt -->
<div class="form-group">
{{ form.username.label(class="form-control-label") }}
{% if form.username.errors %}
{{ form.username(class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.username.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.username(class="form-control form-control-lg") }}
{% endif %}
</div>
<!-- Password-felt -->
<div class="form-group">
{{ form.password.label(class="form-control-label") }}
{% if form.password.errors %}
{{ form.password(class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.password.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.password(class="form-control form-control-lg") }}
{% endif %}
</div>
</fieldset>
<!-- Submit-knap -->
<div class="form-group">
{{ form.submit(class="btn btn-outline-info") }}
</div>
</form>
{% endblock content %}

View File

@ -4,7 +4,7 @@
<h1>{{ thread.title }}</h1>
<div id="messages" class="messages">
{% for message in messages %}
{% if message.author_id == current_user.user_id %}
{% if message.author.user_id == current_user.user_id %}
<div class="message-container self">
{% else %}
<div class="message-container">
@ -30,3 +30,8 @@
</script>
</div>
{% endblock content %}
{% block sidebar %}
<a class="group-name" href="{{ url_for('Group.show', group_id = thread.group_id) }}">{{thread.group.name}}</a>
{% endblock sidebar %}

View File

@ -5,6 +5,7 @@
{% for thread in threads %}
<div class="content-section">
<a class="thread-name" href="{{ url_for('Threads.show', thread_id = thread.thread_id) }}"">{{thread.title}}</a>
<a class="float-right group-name" href="{{ url_for('Group.show', group_id = thread.group_id) }}">{{thread.group.name}}</a>
</div>
{% endfor %}
{% endblock content %}

View File

@ -1,46 +0,0 @@
{% extends "layout.html" %}
{% block content %}
<div class="content-section">
<form method="POST" action="">
{{ form.hidden_tag() }}
<div class="form-group">
{{ form.sourceAccount.label(class="form-control-label") }}
{{ form.sourceAccount(class="form-control")}}
</div>
<fieldset class="form-group">
<div class="form-group">
{{ form.amount.label(class="form-control-label") }}
{% if form.amount.errors %}
{{ form.amount(class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.password.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.amount(class="form-control form-control-lg") }}
{% endif %}
</div>
</fieldset>
<div class="form-group">
{{ form.targetAccount.label(class="form-control-label") }}
{{ form.targetAccount(class="form-control") }}
</div>
<div class="form-group">
{{ form.submit(class="btn btn-outline-info") }}
</div>
</form>
</div>
<div class="content-section">
<p>Dropdown customer account tuples:</p>
<ul class="list-group">
{% for n in drop_cus_acc %}
<li class="list-group-item list-group-item-light">{{n}}}</li>
{% endfor %}
</ul>
<br>
<p>Same list with a filter: {{ drop_cus_acc|join(', ') }}</p>
</div>
{% endblock content %}