# Display Help | # Display Help | ||||
echo "This script performs database functions for the ExPub Compendium" | echo "This script performs database functions for the ExPub Compendium" | ||||
echo | echo | ||||
echo "Syntax: database_functions.sh [-l|h|e|i|c]" | |||||
echo "Syntax: database_functions.sh [-l|h|e|i|c|v|d]" | |||||
echo "options:" | echo "options:" | ||||
echo "l Print the MIT License notification." | echo "l Print the MIT License notification." | ||||
echo "h Print this Help." | echo "h Print this Help." | ||||
echo "i Import whole database." | echo "i Import whole database." | ||||
echo "c Export single table as tab-delimited txt." | echo "c Export single table as tab-delimited txt." | ||||
echo "v Import tab-delimited txt file to table." | echo "v Import tab-delimited txt file to table." | ||||
echo "d Drop table." | |||||
echo | echo | ||||
} | } | ||||
docker exec -i $CONTAINER bash -c "mysql -u $USERNAME -p$PASSWORD $DATABASE -e 'LOAD DATA LOCAL INFILE '\''/tmp/import_file'\'' REPLACE INTO TABLE $TABLE FIELDS TERMINATED BY '\''\t'\'' LINES TERMINATED BY '\''\n'\'' IGNORE 1 ROWS;'" | docker exec -i $CONTAINER bash -c "mysql -u $USERNAME -p$PASSWORD $DATABASE -e 'LOAD DATA LOCAL INFILE '\''/tmp/import_file'\'' REPLACE INTO TABLE $TABLE FIELDS TERMINATED BY '\''\t'\'' LINES TERMINATED BY '\''\n'\'' IGNORE 1 ROWS;'" | ||||
} | } | ||||
Drop_table() | |||||
{ | |||||
docker exec -i $CONTAINER bash -c "mysql -u $USERNAME -p$PASSWORD $DATABASE -e 'DROP TABLE IF EXISTS $TABLE;'" | |||||
} | |||||
############################################################ | ############################################################ | ||||
############################################################ | ############################################################ | ||||
# main program # | # main program # | ||||
# set variables | # set variables | ||||
CONTAINER=mariadb | CONTAINER=mariadb | ||||
DATABASE=toolkit | DATABASE=toolkit | ||||
USERNAME=xxxxxxxx | |||||
PASSWORD=xxxxxxxx | |||||
USERNAME=xxxxxxxxx | |||||
PASSWORD=xxxxxxxxx | |||||
EXPORT_SQL_FILENAME=toolkit_db_ | EXPORT_SQL_FILENAME=toolkit_db_ | ||||
IMPORT_SQL_DIRECTORY="/Users/ad7588/Downloads" | IMPORT_SQL_DIRECTORY="/Users/ad7588/Downloads" | ||||
IMPORT_SQL_FILENAME=toolkit_db.sql | IMPORT_SQL_FILENAME=toolkit_db.sql | ||||
fi | fi | ||||
# get the options | # get the options | ||||
while getopts ":hleicv" flag; do | |||||
while getopts ":hleicvd" flag; do | |||||
case $flag in | case $flag in | ||||
l) # display License | l) # display License | ||||
License | License | ||||
Table_import | Table_import | ||||
exit 1 | exit 1 | ||||
fi;; | fi;; | ||||
d) # drop table | |||||
if [ -z "$2" ] | |||||
then | |||||
echo "-d requires a table name as an argument" | |||||
echo | |||||
echo "Syntax: database_functions.sh -d [table name]" | |||||
else | |||||
TABLE=$2 | |||||
Drop_table | |||||
exit 1 | |||||
fi;; | |||||
\?) # Invalid option | \?) # Invalid option | ||||
Help | Help | ||||
exit;; | exit;; |
# syntax=docker/dockerfile:1 | # syntax=docker/dockerfile:1 | ||||
FROM python:3.8-slim-buster | FROM python:3.8-slim-buster | ||||
RUN apt update && apt install -y apt-transport-https ca-certificates sqlite3 | |||||
WORKDIR /code | WORKDIR /code | ||||
COPY requirements.txt requirements.txt | COPY requirements.txt requirements.txt | ||||
RUN pip install -r requirements.txt | RUN pip install -r requirements.txt |
from flask_login import login_required, current_user | from flask_login import login_required, current_user | ||||
from .models import Resource | from .models import Resource | ||||
from .resources import * | from .resources import * | ||||
from .relationships import * | |||||
from werkzeug.exceptions import abort | from werkzeug.exceptions import abort | ||||
from . import db | from . import db | ||||
import os | import os | ||||
@book.route('/books/<int:book_id>') | @book.route('/books/<int:book_id>') | ||||
def show_book(book_id): | def show_book(book_id): | ||||
book = get_resource(book_id) | book = get_resource(book_id) | ||||
links = get_linked_resources(book_id) | |||||
links = get_relationships(book_id) | |||||
return render_template('resource.html', resource=book, links=links) | return render_template('resource.html', resource=book, links=links) | ||||
# route for editing a single book based on the ID in the database | # route for editing a single book based on the ID in the database |
from .models import Resource | from .models import Resource | ||||
from .models import Relationship | from .models import Relationship | ||||
from .resources import * | from .resources import * | ||||
from .relationships import * | |||||
from werkzeug.exceptions import abort | from werkzeug.exceptions import abort | ||||
from . import db | from . import db | ||||
import os | import os | ||||
if request.form.getlist('linked_resources'): | if request.form.getlist('linked_resources'): | ||||
for linked_resource in request.form.getlist('linked_resources'): | for linked_resource in request.form.getlist('linked_resources'): | ||||
tool = Resource.query.filter_by(type='tool').filter_by(name=name).first() | tool = Resource.query.filter_by(type='tool').filter_by(name=name).first() | ||||
add_linked_resource(tool.id, linked_resource) | |||||
add_relationship(tool.id, linked_resource) | |||||
elif request.form.get('resource_type') == 'practice': | elif request.form.get('resource_type') == 'practice': | ||||
type = 'practice' | type = 'practice' |
type = db.Column(db.Text) | type = db.Column(db.Text) | ||||
name = db.Column(db.Text) | name = db.Column(db.Text) | ||||
description = db.Column(db.Text) | description = db.Column(db.Text) | ||||
developer = db.Column(db.Text) | |||||
developerUrl = db.Column(db.Text) | |||||
projectUrl = db.Column(db.Text) | projectUrl = db.Column(db.Text) | ||||
repositoryUrl = db.Column(db.Text) | repositoryUrl = db.Column(db.Text) | ||||
license = db.Column(db.Text) | |||||
scriptingLanguage = db.Column(db.Text) | |||||
expertiseToUse = db.Column(db.Text) | expertiseToUse = db.Column(db.Text) | ||||
expertiseToHost = db.Column(db.Text) | expertiseToHost = db.Column(db.Text) | ||||
dependencies = db.Column(db.Text) | dependencies = db.Column(db.Text) |
from flask_login import login_required, current_user | from flask_login import login_required, current_user | ||||
from .models import Resource | from .models import Resource | ||||
from .resources import * | from .resources import * | ||||
from .relationships import * | |||||
from werkzeug.exceptions import abort | from werkzeug.exceptions import abort | ||||
from . import db | from . import db | ||||
import os | import os | ||||
@practice.route('/practices/<int:practice_id>') | @practice.route('/practices/<int:practice_id>') | ||||
def show_practice(practice_id): | def show_practice(practice_id): | ||||
practice = get_resource(practice_id) | practice = get_resource(practice_id) | ||||
links = get_linked_resources(practice_id) | |||||
links = get_relationships(practice_id) | |||||
return render_template('resource.html', resource=practice, links=links) | return render_template('resource.html', resource=practice, links=links) | ||||
# route for editing a single practice based on the ID in the database | # route for editing a single practice based on the ID in the database | ||||
def edit_practice(practice_id): | def edit_practice(practice_id): | ||||
practice = get_resource(practice_id) | practice = get_resource(practice_id) | ||||
resource_dropdown = Resource.query | resource_dropdown = Resource.query | ||||
links = get_linked_resources(practice_id) | |||||
existing_relationships = get_relationships(practice_id) | |||||
if request.method == 'POST': | if request.method == 'POST': | ||||
name = request.form['name'] | name = request.form['name'] | ||||
if linked_resources: | if linked_resources: | ||||
for linked_resource in linked_resources: | for linked_resource in linked_resources: | ||||
link = Resource.query.get(linked_resource) | link = Resource.query.get(linked_resource) | ||||
if links and link not in links: | |||||
add_linked_resource(practice_id, linked_resource) | |||||
elif not links: | |||||
add_linked_resource(practice_id, linked_resource) | |||||
if existing_relationships and link not in existing_relationships: | |||||
add_relationship(practice_id, linked_resource) | |||||
elif not existing_relationships: | |||||
add_relationship(practice_id, linked_resource) | |||||
if remove_linked_resources: | if remove_linked_resources: | ||||
for remove_linked_resource in remove_linked_resources: | for remove_linked_resource in remove_linked_resources: | ||||
delete_relationship(practice_id, remove_linked_resource) | delete_relationship(practice_id, remove_linked_resource) | ||||
return redirect(url_for('practice.get_practices',_external=True,_scheme=os.environ.get('SSL_SCHEME'))) | return redirect(url_for('practice.get_practices',_external=True,_scheme=os.environ.get('SSL_SCHEME'))) | ||||
return render_template('edit.html', resource=practice, resource_dropdown=resource_dropdown, links=links) | |||||
return render_template('edit.html', resource=practice, resource_dropdown=resource_dropdown, links=existing_relationships) | |||||
# route for function to delete a single practice from the edit page | # route for function to delete a single practice from the edit page | ||||
@practice.route('/practices/<int:practice_id>/delete', methods=('POST',)) | @practice.route('/practices/<int:practice_id>/delete', methods=('POST',)) |
from flask_login import login_required, current_user | from flask_login import login_required, current_user | ||||
from .models import Resource | from .models import Resource | ||||
from .resources import * | from .resources import * | ||||
from .relationships import * | |||||
from werkzeug.exceptions import abort | from werkzeug.exceptions import abort | ||||
from . import db | from . import db | ||||
import os | import os | ||||
@publisher.route('/publishers/<int:publisher_id>') | @publisher.route('/publishers/<int:publisher_id>') | ||||
def show_publisher(publisher_id): | def show_publisher(publisher_id): | ||||
publisher = get_resource(publisher_id) | publisher = get_resource(publisher_id) | ||||
links = get_linked_resources(publisher_id) | |||||
links = get_relationships(publisher_id) | |||||
return render_template('resource.html', resource=publisher, links=links) | return render_template('resource.html', resource=publisher, links=links) | ||||
# route for editing a single publisher based on the ID in the database | # route for editing a single publisher based on the ID in the database |
# @name: relationships.py | |||||
# @creation_date: 2022-04-11 | |||||
# @license: The MIT License <https://opensource.org/licenses/MIT> | |||||
# @author: Simon Bowie <ad7588@coventry.ac.uk> | |||||
# @purpose: functions for relationships | |||||
# @acknowledgements: | |||||
from flask import Blueprint, render_template, request, flash, redirect, url_for | |||||
from .models import Resource | |||||
from .models import Relationship | |||||
from werkzeug.exceptions import abort | |||||
from . import db | |||||
# function to retrieve linked resources | |||||
def get_relationships(primary_id): | |||||
primary_relationships = Relationship.query.filter_by(first_resource_id=primary_id).all() | |||||
links = [] | |||||
if primary_relationships: | |||||
links = [] | |||||
for relationship in primary_relationships: | |||||
secondary_id = relationship.second_resource_id | |||||
links.extend(Resource.query.filter_by(id=secondary_id).all()) | |||||
secondary_relationships = Relationship.query.filter_by(second_resource_id=primary_id).all() | |||||
if secondary_relationships: | |||||
for relationship in secondary_relationships: | |||||
primary_id = relationship.first_resource_id | |||||
links.extend(Resource.query.filter_by(id=primary_id).all()) | |||||
return links | |||||
else: | |||||
secondary_relationships = Relationship.query.filter_by(second_resource_id=primary_id).all() | |||||
if secondary_relationships: | |||||
links = [] | |||||
for relationship in secondary_relationships: | |||||
primary_id = relationship.first_resource_id | |||||
links.extend(Resource.query.filter_by(id=primary_id).all()) | |||||
return links | |||||
# function to add a relationship to a linked resource | |||||
def add_relationship(resource_id, linked_resource_id): | |||||
first_resource_id = resource_id | |||||
second_resource_id = linked_resource_id | |||||
new_relationship = Relationship(first_resource_id=first_resource_id, second_resource_id=second_resource_id) | |||||
# add the new relationship to the database | |||||
db.session.add(new_relationship) | |||||
db.session.commit() | |||||
# function to delete a single relationship | |||||
def delete_relationship(main_id, for_deletion_id): | |||||
relation = Relationship.query.filter(((Relationship.first_resource_id == main_id) & (Relationship.second_resource_id == for_deletion_id)) | ((Relationship.first_resource_id == for_deletion_id) & (Relationship.second_resource_id == main_id))).first() | |||||
deletion = Relationship.query.get(relation.id) | |||||
db.session.delete(deletion) | |||||
db.session.commit() |
from flask import Blueprint, render_template, request, flash, redirect, url_for | from flask import Blueprint, render_template, request, flash, redirect, url_for | ||||
from flask_login import login_required, current_user | from flask_login import login_required, current_user | ||||
from .models import Resource | from .models import Resource | ||||
from .models import Relationship | |||||
from werkzeug.exceptions import abort | from werkzeug.exceptions import abort | ||||
from . import db | from . import db | ||||
abort(404) | abort(404) | ||||
return resource | return resource | ||||
# function to retrieve linked resources | |||||
def get_linked_resources(primary_id): | |||||
primary_relationships = Relationship.query.filter_by(first_resource_id=primary_id).all() | |||||
links = [] | |||||
if primary_relationships: | |||||
links = [] | |||||
for relationship in primary_relationships: | |||||
secondary_id = relationship.second_resource_id | |||||
links.extend(Resource.query.filter_by(id=secondary_id).all()) | |||||
secondary_relationships = Relationship.query.filter_by(second_resource_id=primary_id).all() | |||||
if secondary_relationships: | |||||
for relationship in secondary_relationships: | |||||
primary_id = relationship.first_resource_id | |||||
links.extend(Resource.query.filter_by(id=primary_id).all()) | |||||
return links | |||||
else: | |||||
secondary_relationships = Relationship.query.filter_by(second_resource_id=primary_id).all() | |||||
if secondary_relationships: | |||||
links = [] | |||||
for relationship in secondary_relationships: | |||||
primary_id = relationship.first_resource_id | |||||
links.extend(Resource.query.filter_by(id=primary_id).all()) | |||||
return links | |||||
# function to add a relationship to a linked resource | |||||
def add_linked_resource(resource_id, linked_resource_id): | |||||
first_resource_id = resource_id | |||||
second_resource_id = linked_resource_id | |||||
new_relationship = Relationship(first_resource_id=first_resource_id, second_resource_id=second_resource_id) | |||||
# add the new relationship to the database | |||||
db.session.add(new_relationship) | |||||
db.session.commit() | |||||
# function to delete a single resource | # function to delete a single resource | ||||
def delete_resource(resource_id): | def delete_resource(resource_id): | ||||
deletion = Resource.query.get(resource_id) | deletion = Resource.query.get(resource_id) | ||||
db.session.delete(deletion) | db.session.delete(deletion) | ||||
db.session.commit() | db.session.commit() | ||||
flash('Successfully deleted!') | flash('Successfully deleted!') | ||||
# function to delete a single relationship | |||||
def delete_relationship(main_id, for_deletion_id): | |||||
relation = Relationship.query.filter(((Relationship.first_resource_id == main_id) & (Relationship.second_resource_id == for_deletion_id)) | ((Relationship.first_resource_id == for_deletion_id) & (Relationship.second_resource_id == main_id))).first() | |||||
deletion = Relationship.query.get(relation.id) | |||||
db.session.delete(deletion) | |||||
db.session.commit() |
{% extends 'base.html' %} | {% extends 'base.html' %} | ||||
{% block content %} | {% block content %} | ||||
{{linked_resources}} | |||||
<h1>{% block title %} Edit "{{ resource['name'] }}" {% endblock %}</h1> | <h1>{% block title %} Edit "{{ resource['name'] }}" {% endblock %}</h1> | ||||
<form method="post"> | <form method="post"> | ||||
{% for resource_dropdown in resource_dropdown %} | {% for resource_dropdown in resource_dropdown %} | ||||
{% if resource_dropdown['type'] != 'tool' %} | {% if resource_dropdown['type'] != 'tool' %} | ||||
{% if links and resource_dropdown in links %} | {% if links and resource_dropdown in links %} | ||||
<option value="" selected>{{ resource_dropdown['name'] }}</option> | |||||
<option value="{{ resource_dropdown['id'] }}" selected>{{ resource_dropdown['name'] }}</option> | |||||
{% else %} | {% else %} | ||||
<option value="{{ resource_dropdown['id'] }}">{{ resource_dropdown['name'] }}</option> | <option value="{{ resource_dropdown['id'] }}">{{ resource_dropdown['name'] }}</option> | ||||
{% endif %} | {% endif %} | ||||
{% for resource_dropdown in resource_dropdown %} | {% for resource_dropdown in resource_dropdown %} | ||||
{% if resource_dropdown['type'] != 'practice' %} | {% if resource_dropdown['type'] != 'practice' %} | ||||
{% if links and resource_dropdown in links %} | {% if links and resource_dropdown in links %} | ||||
<option value="" selected>{{ resource_dropdown['name'] }}</option> | |||||
<option value="{{ resource_dropdown['id'] }}" selected>{{ resource_dropdown['name'] }}</option> | |||||
{% else %} | {% else %} | ||||
<option value="{{ resource_dropdown['id'] }}">{{ resource_dropdown['name'] }}</option> | <option value="{{ resource_dropdown['id'] }}">{{ resource_dropdown['name'] }}</option> | ||||
{% endif %} | {% endif %} |
{% extends 'base.html' %} | {% extends 'base.html' %} | ||||
{% block content %} | {% block content %} | ||||
{{linked_resources}} | |||||
<div class="row"> | <div class="row"> | ||||
<div class="col"> | <div class="col"> | ||||
<h1 class="text-center">{% block title %} {{ resource['name'] }} {% endblock %}</h1> | <h1 class="text-center">{% block title %} {{ resource['name'] }} {% endblock %}</h1> |
from flask_login import login_required, current_user | from flask_login import login_required, current_user | ||||
from .models import Resource | from .models import Resource | ||||
from .resources import * | from .resources import * | ||||
from .relationships import * | |||||
from werkzeug.exceptions import abort | from werkzeug.exceptions import abort | ||||
from . import db | from . import db | ||||
import os | import os | ||||
@tool.route('/tools/<int:tool_id>') | @tool.route('/tools/<int:tool_id>') | ||||
def show_tool(tool_id): | def show_tool(tool_id): | ||||
tool = get_resource(tool_id) | tool = get_resource(tool_id) | ||||
links = get_linked_resources(tool_id) | |||||
links = get_relationships(tool_id) | |||||
return render_template('resource.html', resource=tool, links=links) | return render_template('resource.html', resource=tool, links=links) | ||||
# route for editing a single tool based on the ID in the database | # route for editing a single tool based on the ID in the database | ||||
def edit_tool(tool_id): | def edit_tool(tool_id): | ||||
tool = get_resource(tool_id) | tool = get_resource(tool_id) | ||||
resource_dropdown = Resource.query | resource_dropdown = Resource.query | ||||
links = get_linked_resources(tool_id) | |||||
existing_relationships = get_relationships(tool_id) | |||||
if request.method == 'POST': | if request.method == 'POST': | ||||
name = request.form['name'] | name = request.form['name'] | ||||
if linked_resources: | if linked_resources: | ||||
for linked_resource in linked_resources: | for linked_resource in linked_resources: | ||||
link = Resource.query.get(linked_resource) | link = Resource.query.get(linked_resource) | ||||
if links and link not in links: | |||||
add_linked_resource(tool_id, linked_resource) | |||||
elif not links: | |||||
add_linked_resource(tool_id, linked_resource) | |||||
if existing_relationships and link not in existing_relationships: | |||||
add_relationship(tool_id, linked_resource) | |||||
elif not existing_relationships: | |||||
add_relationship(tool_id, linked_resource) | |||||
if remove_linked_resources: | if remove_linked_resources: | ||||
for remove_linked_resource in remove_linked_resources: | for remove_linked_resource in remove_linked_resources: | ||||
delete_relationship(tool_id, remove_linked_resource) | delete_relationship(tool_id, remove_linked_resource) | ||||
return redirect(url_for('tool.get_tools',_external=True,_scheme=os.environ.get('SSL_SCHEME'))) | return redirect(url_for('tool.get_tools',_external=True,_scheme=os.environ.get('SSL_SCHEME'))) | ||||
return render_template('edit.html', resource=tool, resource_dropdown=resource_dropdown, links=links) | |||||
return render_template('edit.html', resource=tool, resource_dropdown=resource_dropdown, links=existing_relationships) | |||||
# route for function to delete a single tool from the edit page | # route for function to delete a single tool from the edit page | ||||
@tool.route('/tools/<int:tool_id>/delete', methods=('POST',)) | @tool.route('/tools/<int:tool_id>/delete', methods=('POST',)) |