The online toolkit will build on this review of tools to present a resource for a researcher, artist, or publisher looking to try experimental publishing. From our preliminary design discussions, we have plans to include not only software tools that can be used to do experimental publishing but examples of experimental publications, practices of experimental publishing, publishers who have done some form of experimental publishing, and sensitivities involved in experimental publishing. | The online toolkit will build on this review of tools to present a resource for a researcher, artist, or publisher looking to try experimental publishing. From our preliminary design discussions, we have plans to include not only software tools that can be used to do experimental publishing but examples of experimental publications, practices of experimental publishing, publishers who have done some form of experimental publishing, and sensitivities involved in experimental publishing. | ||||
## Database functions | |||||
This repository contains a shell script to perform various database functions including importing a whole database from SQL file, exporting the database in SQL, exporting individual tables as tab-delimited txt file, and importing individual tables from tab-delimited txt file. | |||||
Run `./database_functions -h` to see the instructions for this script. | |||||
## Legacy instructions: | |||||
The following is no longer required in Flask-SQLAlchemy 3. See https://stackoverflow.com/questions/73968584/flask-sqlalchemy-db-create-all-got-an-unexpected-keyword-argument-app | |||||
For creating database and user in production: | For creating database and user in production: | ||||
`docker-compose exec -it db mysql -u root -p` | `docker-compose exec -it db mysql -u root -p` | ||||
`CREATE USER 'flask'@'%' IDENTIFIED BY '[PASSWORD]';` | `CREATE USER 'flask'@'%' IDENTIFIED BY '[PASSWORD]';` | ||||
`GRANT CREATE, INSERT, UPDATE, SELECT, DELETE ON toolkit.* TO 'flask'@'%';` | `GRANT CREATE, INSERT, UPDATE, SELECT, DELETE ON toolkit.* TO 'flask'@'%';` | ||||
## Legacy instructions: | |||||
The following is no longer required in Flask-SQLAlchemy 3. See https://stackoverflow.com/questions/73968584/flask-sqlalchemy-db-create-all-got-an-unexpected-keyword-argument-app | |||||
To build the database run: | To build the database run: | ||||
`docker exec -it python python` | `docker exec -it python python` |
book = get_resource(book_id) | book = get_resource(book_id) | ||||
if request.method == 'POST': | if request.method == 'POST': | ||||
name = request.form['name'] | |||||
description = request.form['description'] | |||||
if not name: | |||||
if not request.form['name']: | |||||
flash('Name is required!') | flash('Name is required!') | ||||
else: | else: | ||||
book = Resource.query.get(book_id) | book = Resource.query.get(book_id) | ||||
book.name = name | |||||
book.description = description | |||||
book.name = request.form['name'] | |||||
book.description = request.form['description'] | |||||
db.session.commit() | db.session.commit() | ||||
return redirect(url_for('book.get_books',_external=True,_scheme=os.environ.get('SSL_SCHEME'))) | return redirect(url_for('book.get_books',_external=True,_scheme=os.environ.get('SSL_SCHEME'))) | ||||
@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_relationships(practice_id) | |||||
return render_template('resource.html', resource=practice, links=links) | |||||
relationships = get_relationships(practice_id) | |||||
return render_template('resource.html', resource=practice, relationships=relationships) | |||||
# 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 | ||||
@practice.route('/practices/<int:practice_id>/edit', methods=('GET', 'POST')) | @practice.route('/practices/<int:practice_id>/edit', methods=('GET', 'POST')) | ||||
existing_relationships = get_relationships(practice_id) | existing_relationships = get_relationships(practice_id) | ||||
if request.method == 'POST': | if request.method == 'POST': | ||||
name = request.form['name'] | |||||
description = request.form['description'] | |||||
linked_resources = request.form.getlist('linked_resources') | |||||
remove_linked_resources = request.form.getlist('remove_linked_resources') | |||||
if not name: | |||||
if not request.form['name']: | |||||
flash('Name is required!') | flash('Name is required!') | ||||
else: | else: | ||||
practice = Resource.query.get(practice_id) | practice = Resource.query.get(practice_id) | ||||
practice.name = name | |||||
practice.description = description | |||||
practice.name = request.form['name'] | |||||
practice.description = request.form['description'] | |||||
db.session.commit() | db.session.commit() | ||||
linked_resources = request.form.getlist('linked_resources') | |||||
remove_linked_resources = request.form.getlist('remove_linked_resources') | |||||
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) |
publisher = get_resource(publisher_id) | publisher = get_resource(publisher_id) | ||||
if request.method == 'POST': | if request.method == 'POST': | ||||
name = request.form['name'] | |||||
description = request.form['description'] | |||||
if not name: | |||||
if not request.form['name']: | |||||
flash('Name is required!') | flash('Name is required!') | ||||
else: | else: | ||||
publisher = Resource.query.get(publisher_id) | publisher = Resource.query.get(publisher_id) | ||||
publisher.name = name | |||||
publisher.description = description | |||||
publisher.name = request.form['name'] | |||||
publisher.description = request.form['description'] | |||||
db.session.commit() | db.session.commit() | ||||
return redirect(url_for('publisher.get_publishers',_external=True,_scheme=os.environ.get('SSL_SCHEME'))) | return redirect(url_for('publisher.get_publishers',_external=True,_scheme=os.environ.get('SSL_SCHEME'))) | ||||
{% 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> | ||||
</table> | </table> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
{% if links %} | |||||
{% if relationships %} | |||||
<div class="row"> | <div class="row"> | ||||
<div class="col"> | <div class="col"> | ||||
<h2 class="text-center">Linked resources:</h2> | <h2 class="text-center">Linked resources:</h2> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="row"> | <div class="row"> | ||||
{% for link in links %} | |||||
{% for relationship in relationships %} | |||||
<div class="col-md-4 col-sm-6 py-3"> | <div class="col-md-4 col-sm-6 py-3"> | ||||
{% if link['type'] == 'tool' %} | |||||
{% if relationship['type'] == 'tool' %} | |||||
<div class="card text-dark bg-tool mb-3"> | <div class="card text-dark bg-tool mb-3"> | ||||
<div class="card-body"> | <div class="card-body"> | ||||
<a href="{{ url_for('tool.show_tool', tool_id=link['id']) }}"> | |||||
<h3 class="card-title text-center text-dark">{{ link['name'] }}</h3> | |||||
<a href="{{ url_for('tool.show_tool', tool_id=relationship['id']) }}"> | |||||
<h3 class="card-title text-center text-dark">{{ relationship['name'] }}</h3> | |||||
</a> | </a> | ||||
<p class="card-text"> | <p class="card-text"> | ||||
{{ link['description']|truncate(100) }} | |||||
{{ relationship['description']|truncate(100) }} | |||||
</p> | </p> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
{% endif %} | {% endif %} | ||||
{% if link['type'] == 'practice' %} | |||||
{% if relationship['type'] == 'practice' %} | |||||
<div class="card text-dark bg-practice mb-3"> | <div class="card text-dark bg-practice mb-3"> | ||||
<div class="card-body"> | <div class="card-body"> | ||||
<a href="{{ url_for('practice.show_practice', practice_id=link['id']) }}"> | |||||
<h3 class="card-title text-center text-dark">{{ link['name'] }}</h3> | |||||
<a href="{{ url_for('practice.show_practice', practice_id=relationship['id']) }}"> | |||||
<h3 class="card-title text-center text-dark">{{ relationship['name'] }}</h3> | |||||
</a> | </a> | ||||
<p class="card-text"> | <p class="card-text"> | ||||
{{ link['description']|truncate(100) }} | |||||
{{ relationship['description']|truncate(100) }} | |||||
</p> | </p> | ||||
</div> | </div> | ||||
</div> | </div> |
@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_relationships(tool_id) | |||||
return render_template('resource.html', resource=tool, links=links) | |||||
relationships = get_relationships(tool_id) | |||||
return render_template('resource.html', resource=tool, relationships=relationships) | |||||
# 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 | ||||
@tool.route('/tools/<int:tool_id>/edit', methods=('GET', 'POST')) | @tool.route('/tools/<int:tool_id>/edit', methods=('GET', 'POST')) | ||||
existing_relationships = get_relationships(tool_id) | existing_relationships = get_relationships(tool_id) | ||||
if request.method == 'POST': | if request.method == 'POST': | ||||
name = request.form['name'] | |||||
description = request.form['description'] | |||||
developer = request.form['developer'] | |||||
developerUrl = request.form['developerUrl'] | |||||
projectUrl = request.form['projectUrl'] | |||||
repositoryUrl = request.form['repositoryUrl'] | |||||
license = request.form['license'] | |||||
scriptingLanguage = request.form['scriptingLanguage'] | |||||
expertiseToUse = request.form['expertiseToUse'] | |||||
expertiseToHost = request.form['expertiseToHost'] | |||||
dependencies = request.form['dependencies'] | |||||
ingestFormats = request.form['ingestFormats'] | |||||
outputFormats = request.form['outputFormats'] | |||||
status = request.form['status'] | |||||
linked_resources = request.form.getlist('linked_resources') | |||||
remove_linked_resources = request.form.getlist('remove_linked_resources') | |||||
if not name: | |||||
if not request.form['name']: | |||||
flash('Name is required!') | flash('Name is required!') | ||||
else: | else: | ||||
tool = Resource.query.get(tool_id) | tool = Resource.query.get(tool_id) | ||||
tool.name = name | |||||
tool.description = description | |||||
tool.developer = developer | |||||
tool.developerUrl = developerUrl | |||||
tool.projectUrl = projectUrl | |||||
tool.repositoryUrl = repositoryUrl | |||||
tool.license = license | |||||
tool.scriptingLanguage = scriptingLanguage | |||||
tool.dependencies = dependencies | |||||
tool.expertiseToUse = expertiseToUse | |||||
tool.expertiseToHost = expertiseToHost | |||||
tool.ingestFormats = ingestFormats | |||||
tool.outputFormats = outputFormats | |||||
tool.status = status | |||||
tool.name = request.form['name'] | |||||
tool.description = request.form['description'] | |||||
tool.developer = request.form['developer'] | |||||
tool.developerUrl = request.form['developerUrl'] | |||||
tool.projectUrl = request.form['projectUrl'] | |||||
tool.repositoryUrl = request.form['repositoryUrl'] | |||||
tool.license = request.form['license'] | |||||
tool.scriptingLanguage = request.form['scriptingLanguage'] | |||||
tool.expertiseToUse = request.form['expertiseToUse'] | |||||
tool.expertiseToHost = request.form['expertiseToHost'] | |||||
tool.dependencies = request.form['dependencies'] | |||||
tool.ingestFormats = request.form['ingestFormats'] | |||||
tool.outputFormats = request.form['outputFormats'] | |||||
tool.status = request.form['status'] | |||||
db.session.commit() | db.session.commit() | ||||
linked_resources = request.form.getlist('linked_resources') | |||||
remove_linked_resources = request.form.getlist('remove_linked_resources') | |||||
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) |