@@ -26,7 +26,7 @@ Help() | |||
# Display Help | |||
echo "This script performs database functions for the ExPub Compendium" | |||
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 "l Print the MIT License notification." | |||
echo "h Print this Help." | |||
@@ -34,6 +34,7 @@ Help() | |||
echo "i Import whole database." | |||
echo "c Export single table as tab-delimited txt." | |||
echo "v Import tab-delimited txt file to table." | |||
echo "d Drop table." | |||
echo | |||
} | |||
@@ -58,6 +59,11 @@ Table_import() | |||
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 # | |||
@@ -67,8 +73,8 @@ Table_import() | |||
# set variables | |||
CONTAINER=mariadb | |||
DATABASE=toolkit | |||
USERNAME=xxxxxxxx | |||
PASSWORD=xxxxxxxx | |||
USERNAME=xxxxxxxxx | |||
PASSWORD=xxxxxxxxx | |||
EXPORT_SQL_FILENAME=toolkit_db_ | |||
IMPORT_SQL_DIRECTORY="/Users/ad7588/Downloads" | |||
IMPORT_SQL_FILENAME=toolkit_db.sql | |||
@@ -82,7 +88,7 @@ if (( $# == 0 )); then | |||
fi | |||
# get the options | |||
while getopts ":hleicv" flag; do | |||
while getopts ":hleicvd" flag; do | |||
case $flag in | |||
l) # display License | |||
License | |||
@@ -119,6 +125,17 @@ while getopts ":hleicv" flag; do | |||
Table_import | |||
exit 1 | |||
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 | |||
Help | |||
exit;; |
@@ -1,5 +1,6 @@ | |||
# syntax=docker/dockerfile:1 | |||
FROM python:3.8-slim-buster | |||
RUN apt update && apt install -y apt-transport-https ca-certificates sqlite3 | |||
WORKDIR /code | |||
COPY requirements.txt requirements.txt | |||
RUN pip install -r requirements.txt |
@@ -10,6 +10,7 @@ from flask import Blueprint, render_template, request, flash, redirect, url_for | |||
from flask_login import login_required, current_user | |||
from .models import Resource | |||
from .resources import * | |||
from .relationships import * | |||
from werkzeug.exceptions import abort | |||
from . import db | |||
import os | |||
@@ -26,7 +27,7 @@ def get_books(): | |||
@book.route('/books/<int:book_id>') | |||
def show_book(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) | |||
# route for editing a single book based on the ID in the database |
@@ -11,6 +11,7 @@ from flask_login import login_required, current_user | |||
from .models import Resource | |||
from .models import Relationship | |||
from .resources import * | |||
from .relationships import * | |||
from werkzeug.exceptions import abort | |||
from . import db | |||
import os | |||
@@ -54,7 +55,7 @@ def create_resource(): | |||
if 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() | |||
add_linked_resource(tool.id, linked_resource) | |||
add_relationship(tool.id, linked_resource) | |||
elif request.form.get('resource_type') == 'practice': | |||
type = 'practice' |
@@ -28,8 +28,12 @@ class Resource(db.Model): | |||
type = db.Column(db.Text) | |||
name = db.Column(db.Text) | |||
description = db.Column(db.Text) | |||
developer = db.Column(db.Text) | |||
developerUrl = db.Column(db.Text) | |||
projectUrl = db.Column(db.Text) | |||
repositoryUrl = db.Column(db.Text) | |||
license = db.Column(db.Text) | |||
scriptingLanguage = db.Column(db.Text) | |||
expertiseToUse = db.Column(db.Text) | |||
expertiseToHost = db.Column(db.Text) | |||
dependencies = db.Column(db.Text) |
@@ -10,6 +10,7 @@ from flask import Blueprint, render_template, request, flash, redirect, url_for | |||
from flask_login import login_required, current_user | |||
from .models import Resource | |||
from .resources import * | |||
from .relationships import * | |||
from werkzeug.exceptions import abort | |||
from . import db | |||
import os | |||
@@ -26,7 +27,7 @@ def get_practices(): | |||
@practice.route('/practices/<int:practice_id>') | |||
def show_practice(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) | |||
# route for editing a single practice based on the ID in the database | |||
@@ -35,7 +36,7 @@ def show_practice(practice_id): | |||
def edit_practice(practice_id): | |||
practice = get_resource(practice_id) | |||
resource_dropdown = Resource.query | |||
links = get_linked_resources(practice_id) | |||
existing_relationships = get_relationships(practice_id) | |||
if request.method == 'POST': | |||
name = request.form['name'] | |||
@@ -53,16 +54,16 @@ def edit_practice(practice_id): | |||
if linked_resources: | |||
for linked_resource in linked_resources: | |||
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: | |||
for remove_linked_resource in remove_linked_resources: | |||
delete_relationship(practice_id, remove_linked_resource) | |||
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 | |||
@practice.route('/practices/<int:practice_id>/delete', methods=('POST',)) |
@@ -10,6 +10,7 @@ from flask import Blueprint, render_template, request, flash, redirect, url_for | |||
from flask_login import login_required, current_user | |||
from .models import Resource | |||
from .resources import * | |||
from .relationships import * | |||
from werkzeug.exceptions import abort | |||
from . import db | |||
import os | |||
@@ -26,7 +27,7 @@ def get_publishers(): | |||
@publisher.route('/publishers/<int:publisher_id>') | |||
def show_publisher(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) | |||
# route for editing a single publisher based on the ID in the database |
@@ -0,0 +1,53 @@ | |||
# @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() |
@@ -8,7 +8,6 @@ | |||
from flask import Blueprint, render_template, request, flash, redirect, url_for | |||
from flask_login import login_required, current_user | |||
from .models import Resource | |||
from .models import Relationship | |||
from werkzeug.exceptions import abort | |||
from . import db | |||
@@ -19,50 +18,9 @@ def get_resource(resource_id): | |||
abort(404) | |||
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 | |||
def delete_resource(resource_id): | |||
deletion = Resource.query.get(resource_id) | |||
db.session.delete(deletion) | |||
db.session.commit() | |||
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() |
@@ -1,6 +1,9 @@ | |||
{% extends 'base.html' %} | |||
{% block content %} | |||
{{linked_resources}} | |||
<h1>{% block title %} Edit "{{ resource['name'] }}" {% endblock %}</h1> | |||
<form method="post"> | |||
@@ -83,7 +86,7 @@ | |||
{% for resource_dropdown in resource_dropdown %} | |||
{% if resource_dropdown['type'] != 'tool' %} | |||
{% 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 %} | |||
<option value="{{ resource_dropdown['id'] }}">{{ resource_dropdown['name'] }}</option> | |||
{% endif %} | |||
@@ -101,7 +104,7 @@ | |||
{% for resource_dropdown in resource_dropdown %} | |||
{% if resource_dropdown['type'] != 'practice' %} | |||
{% 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 %} | |||
<option value="{{ resource_dropdown['id'] }}">{{ resource_dropdown['name'] }}</option> | |||
{% endif %} |
@@ -1,6 +1,9 @@ | |||
{% extends 'base.html' %} | |||
{% block content %} | |||
{{linked_resources}} | |||
<div class="row"> | |||
<div class="col"> | |||
<h1 class="text-center">{% block title %} {{ resource['name'] }} {% endblock %}</h1> |
@@ -10,6 +10,7 @@ from flask import Blueprint, render_template, request, flash, redirect, url_for | |||
from flask_login import login_required, current_user | |||
from .models import Resource | |||
from .resources import * | |||
from .relationships import * | |||
from werkzeug.exceptions import abort | |||
from . import db | |||
import os | |||
@@ -26,7 +27,7 @@ def get_tools(): | |||
@tool.route('/tools/<int:tool_id>') | |||
def show_tool(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) | |||
# route for editing a single tool based on the ID in the database | |||
@@ -35,7 +36,7 @@ def show_tool(tool_id): | |||
def edit_tool(tool_id): | |||
tool = get_resource(tool_id) | |||
resource_dropdown = Resource.query | |||
links = get_linked_resources(tool_id) | |||
existing_relationships = get_relationships(tool_id) | |||
if request.method == 'POST': | |||
name = request.form['name'] | |||
@@ -69,16 +70,16 @@ def edit_tool(tool_id): | |||
if linked_resources: | |||
for linked_resource in linked_resources: | |||
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: | |||
for remove_linked_resource in remove_linked_resources: | |||
delete_relationship(tool_id, remove_linked_resource) | |||
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 | |||
@tool.route('/tools/<int:tool_id>/delete', methods=('POST',)) |