| @book.route('/books') | @book.route('/books') | ||||
| def get_books(): | def get_books(): | ||||
| view = request.args.get('view') | view = request.args.get('view') | ||||
| type = 'book' | |||||
| books = Resource.query.filter_by(type=type).all() | |||||
| resource_type = 'book' | |||||
| books_query = Resource.query.filter_by(type=resource_type) | |||||
| for key in request.args.keys(): | for key in request.args.keys(): | ||||
| if key != 'view': | if key != 'view': | ||||
| if key == 'practice': | if key == 'practice': | ||||
| books = Resource.query.join(Relationship, Relationship.first_resource_id == Resource.id, isouter=True).filter(Resource.type==type, Relationship.second_resource_id==request.args.get(key)).all() | |||||
| also_books = Resource.query.join(Relationship, Relationship.second_resource_id == Resource.id, isouter=True).filter(Resource.type==type, Relationship.first_resource_id==request.args.get(key)).all() | |||||
| books = books + also_books | |||||
| else: | |||||
| kwargs = {'type': type, key: request.args.get(key)} | |||||
| books = Resource.query.filter_by(**kwargs).all() | |||||
| books_1 = books_query.join(Relationship, Relationship.first_resource_id == Resource.id, isouter=True).filter(Relationship.second_resource_id==request.args.get(key)) | |||||
| books_2 = books_query.join(Relationship, Relationship.second_resource_id == Resource.id, isouter=True).filter(Relationship.first_resource_id==request.args.get(key)) | |||||
| books_query = books_1.union(books_2) | |||||
| if key != 'practice': | |||||
| kwargs = {key: request.args.get(key)} | |||||
| books_query = books_query.filter_by(**kwargs) | |||||
| # finalise the query | |||||
| books = books_query.all() | |||||
| # get number of books | # get number of books | ||||
| count = len(books) | count = len(books) | ||||
| if view != 'list': | if view != 'list': | ||||
| # append relationships to each book | # append relationships to each book | ||||
| append_relationships_multiple(books) | |||||
| # get filters | |||||
| append_relationships_multiple(books) | |||||
| else: | |||||
| # reorder books by book name | |||||
| books = sorted(books, key=lambda d: d.__dict__['name']) | |||||
| # get values for filters | |||||
| # practices | # practices | ||||
| practices_filter = Resource.query.filter_by(type='practice').with_entities(Resource.id, Resource.name) | |||||
| practices_filter = Resource.query.filter_by(type='practice').with_entities(Resource.id, Resource.name).all() | |||||
| # year | # year | ||||
| year_filter = get_filter_values('year', type) | |||||
| year_filter = get_filter_values('year', resource_type) | |||||
| # typology | # typology | ||||
| typology_filter = get_filter_values('typology', type) | |||||
| return render_template('resources.html', resources=books, type=type, practices_filter=practices_filter, year_filter=year_filter, typology_filter=typology_filter, count=count, view=view) | |||||
| typology_filter = get_filter_values('typology', resource_type) | |||||
| return render_template('resources.html', resources=books, type=resource_type, practices_filter=practices_filter, year_filter=year_filter, typology_filter=typology_filter, count=count, view=view) | |||||
| # route for displaying a single book based on the ID in the database | # route for displaying a single book based on the ID in the database | ||||
| @book.route('/books/<int:book_id>') | @book.route('/books/<int:book_id>') |
| @main.route('/') | @main.route('/') | ||||
| def index(): | def index(): | ||||
| view = request.args.get('view') | view = request.args.get('view') | ||||
| tools = Resource.query.filter_by(type='tool').order_by(func.random()).limit(6).all() | |||||
| if view != 'list': | |||||
| # append relationships to each tool | |||||
| append_relationships_multiple(tools) | |||||
| books = Resource.query.filter_by(type='book').order_by(func.random()).limit(6).all() | |||||
| if view != 'list': | |||||
| # append relationships to each book | |||||
| append_relationships_multiple(books) | |||||
| # curated list of resources to display on homepage | |||||
| tool_ids = ['4','10', '34', '27'] | |||||
| practice_ids = ['53', '59', '65', '56'] | |||||
| book_ids = ['94', '72', '105', '67'] | |||||
| # concatenate lists of resources | |||||
| resource_ids = tool_ids + practice_ids + book_ids | |||||
| # get data for curated resources | |||||
| curated = get_curated_resources(resource_ids) | |||||
| with open('content/home.md', 'r') as f: | with open('content/home.md', 'r') as f: | ||||
| text = f.read() | text = f.read() | ||||
| text = markdown.markdown(text) | text = markdown.markdown(text) | ||||
| book_showcase = get_full_resource('69') | |||||
| return render_template('index.html', text=text, tools=tools, books=books, book=book_showcase, view=view) | |||||
| return render_template('index.html', text=text, resources=curated, view=view) | |||||
| # route for profile page | # route for profile page | ||||
| @main.route('/profile') | @main.route('/profile') |
| from .relationships import * | from .relationships import * | ||||
| from . import db | from . import db | ||||
| import os | import os | ||||
| import markdown | |||||
| practice = Blueprint('practice', __name__) | practice = Blueprint('practice', __name__) | ||||
| if view != 'list': | if view != 'list': | ||||
| # append relationships to each practice | # append relationships to each practice | ||||
| append_relationships_multiple(practices) | append_relationships_multiple(practices) | ||||
| else: | |||||
| # reorder practices by practice name | |||||
| practices = sorted(practices, key=lambda d: d.__dict__['name']) | |||||
| return render_template('resources.html', resources=practices, type='practice', count=count, view=view) | return render_template('resources.html', resources=practices, type='practice', count=count, view=view) | ||||
| # route for displaying a single practice based on the ID in the database | # route for displaying a single practice based on the ID in the database | ||||
| @practice.route('/practices/<int:practice_id>') | @practice.route('/practices/<int:practice_id>') | ||||
| def show_practice(practice_id): | def show_practice(practice_id): | ||||
| practice = get_full_resource(practice_id) | practice = get_full_resource(practice_id) | ||||
| practice.references = replace_urls(practice.references) | |||||
| # render Markdown as HTML | |||||
| practice.longDescription = markdown.markdown(practice.longDescription) | |||||
| practice.experimental = markdown.markdown(practice.experimental) | |||||
| practice.considerations = markdown.markdown(practice.considerations) | |||||
| practice.references = markdown.markdown(practice.references) | |||||
| return render_template('resource.html', resource=practice) | return render_template('resource.html', resource=practice) | ||||
| # 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 |
| from isbntools.app import * | from isbntools.app import * | ||||
| import requests | import requests | ||||
| import re | import re | ||||
| from sqlalchemy.sql import func | |||||
| # function to retrieve data about a single resource from the database | # function to retrieve data about a single resource from the database | ||||
| def get_resource(resource_id): | def get_resource(resource_id): | ||||
| resource.__dict__.update(book_data) | resource.__dict__.update(book_data) | ||||
| return resource | return resource | ||||
| # function to retrieve data about a curated list of resources | |||||
| def get_curated_resources(resource_ids): | |||||
| resources = Resource.query.filter(Resource.id.in_(resource_ids)).order_by(func.random()).all() | |||||
| # append relationships to each resource | |||||
| append_relationships_multiple(resources) | |||||
| return resources | |||||
| # 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) | ||||
| book = meta(isbn) | book = meta(isbn) | ||||
| description = {'desc': desc(isbn)} | description = {'desc': desc(isbn)} | ||||
| book.update(description) | book.update(description) | ||||
| # get highest-resolution book cover possible | |||||
| openl_url = 'https://covers.openlibrary.org/b/isbn/' + book['ISBN-13'] + '-L.jpg?default=false' | |||||
| request = requests.get(openl_url) | |||||
| if request.status_code != 200: | |||||
| book.update(cover(isbn)) | |||||
| else: | |||||
| book_cover = {'thumbnail': openl_url} | |||||
| book.update(book_cover) | |||||
| #book = get_book_cover(book) | |||||
| return book | return book | ||||
| except: | except: | ||||
| pass | pass | ||||
| # function to get full metadata for a book and combine into one object | |||||
| # TO BE DELETED | |||||
| def get_book(resource_id): | |||||
| book = get_resource(resource_id) | |||||
| book_data = get_book_data(book.isbn) | |||||
| book.__dict__.update(book_data) | |||||
| return book | |||||
| # function to replace embedded URL strings with href links | |||||
| def replace_urls(input): | |||||
| # Compile a regular expression to match URLs. | |||||
| # This regular expression is not exhaustive and may not match all possible URLs. | |||||
| # It is intended to be a starting point and can be refined and expanded as needed. | |||||
| url_regex = re.compile(r'((?:https?:(?:/{1,3}|[a-z0-9%])|[a-z0-9.\-]+[.](?:com|net|org|edu|gov|mil|aero|asia|biz|cat|coop|info|int|jobs|mobi|museum|name|post|pro|tel|travel|xxx|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cs|cu|cv|cx|cy|cz|dd|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|Ja|sk|sl|sm|sn|so|sr|ss|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|yu|za|zm|zw)/)(?:[^\s()<>{}\[\]]+|\([^\s()]*?\([^\s()]+\)[^\s()]*?\)|\([^\s]+?\))+(?:\([^\s()]*?\([^\s()]+\)[^\s()]*?\)|\([^\s]+?\)|[^\s`!()\[\]{};:\'\".,<>?«»“”‘’])|(?:(?<!@)[a-z0-9]+(?:[.\-][a-z0-9]+)*[.](?:com|net|org|edu|gov|mil|aero|asia|biz|cat|coop|info|int|jobs|mobi|museum|name|post|pro|tel|travel|xxx|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cs|cu|cv|cx|cy|cz|dd|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|Ja|sk|sl|sm|sn|so|sr|ss|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|yu|za|zm|zw)\b/?(?!@)))') | |||||
| # Find all URLs in the input string using the regular expression. | |||||
| # This will return a list of Match objects, each of which represents a single URL in the string. | |||||
| matches = url_regex.finditer(input) | |||||
| # Iterate over the list of matches and replace each URL with an HTML link. | |||||
| for match in matches: | |||||
| # Get the full URL from the Match object. | |||||
| url = match.group(0) | |||||
| # Create the HTML link by wrapping the URL in an <a> tag. | |||||
| # If the URL does not include a protocol (e.g. "http://" or "https://"), | |||||
| # then add "http://" as the default protocol. | |||||
| if not url.startswith('http'): | |||||
| link = f'<a href="http://{url}">{url}</a>' | |||||
| else: | |||||
| link = f'<a href="{url}">{url}</a>' | |||||
| # Replace the URL in the original string with the HTML link. | |||||
| input = input.replace(url, link) | |||||
| return input | |||||
| # function to get book cover data | |||||
| def get_book_cover(book): | |||||
| # get highest-resolution book cover possible | |||||
| openl_url = 'https://covers.openlibrary.org/b/isbn/' + book['ISBN-13'] + '-L.jpg?default=false' | |||||
| request = requests.get(openl_url) | |||||
| if request.status_code != 200: | |||||
| book.update(cover(isbn)) | |||||
| else: | |||||
| book_cover = {'thumbnail': openl_url} | |||||
| book.update(book_cover) | |||||
| return book |
| > | > | ||||
| {% if (resource['type'] == 'book') %} | |||||
| <img class="w-20 h-20 object-contain float-right m-4 grayscale rotate-[15deg]" src="https://dummyimage.com/4:5x70" alt="cover for {{ resource['name'] }}"> | |||||
| {% if (resource.type == 'book') and (resource.references) %} | |||||
| <img class="w-20 h-20 object-contain float-right m-4 grayscale rotate-[15deg]" src="{{resource.references}}" alt="cover for {{ resource.name }}"> | |||||
| {% endif %} | {% endif %} | ||||
| <h2 class="{{ resource['type'] }} {% if size==1 %} big-title {% else %} small-title {% endif %} mb-2">{{ resource['name'] }}</h2> | <h2 class="{{ resource['type'] }} {% if size==1 %} big-title {% else %} small-title {% endif %} mb-2">{{ resource['name'] }}</h2> | ||||
| <!DOCTYPE html> | <!DOCTYPE html> | ||||
| <html> | |||||
| <html lang="en-gb"> | |||||
| <head> | <head> | ||||
| {{ moment.include_moment() }} | {{ moment.include_moment() }} |
| <div class="left"> | <div class="left"> | ||||
| <div class="mb-2">Book</div> | <div class="mb-2">Book</div> | ||||
| <div class="border-r-2 border-black pr-8"> | <div class="border-r-2 border-black pr-8"> | ||||
| {% if resource['thumbnail'] %} | |||||
| {% if resource.references %} | |||||
| <div class="float-right"> | <div class="float-right"> | ||||
| <img class="w-40 h-40 object-contain m-16 rotate-[15deg]" src={{ resource['thumbnail'] }} alt="cover for {{ resource['Title'] }}"> | |||||
| <img class="w-40 h-40 object-contain m-16 rotate-[15deg]" src={{ resource.references }} alt="cover for {{ resource['Title'] }}"> | |||||
| </div> | </div> | ||||
| {% endif %} | {% endif %} | ||||
| <h2 class="book huge-title mb-2 max-w-[30rem]">{% block title %} {{ resource['Title'] or resource['name'] }} {% endblock %}</h2> | |||||
| <h2 class="book huge-title mb-2 max-w-[30rem]">{% block title %} {{ resource.name }} {% endblock %}</h2> | |||||
| {% if resource['Year'] %} | {% if resource['Year'] %} | ||||
| {{ resource['Year'] }} | {{ resource['Year'] }} |
| <div class="border-b-2 border-black grid gap-8 lg:grid-cols-[52rem,30rem] content-start"> | <div class="border-b-2 border-black grid gap-8 lg:grid-cols-[52rem,30rem] content-start"> | ||||
| <div class="mx-2 lg:ml-[13rem] text my-8 meta max-w-[30rem]"> | <div class="mx-2 lg:ml-[13rem] text my-8 meta max-w-[30rem]"> | ||||
| {{ text|safe }} | {{ text|safe }} | ||||
| <br/> | |||||
| <a href="{{ url_for(request.endpoint, view='list') }}">LIST VIEW</a> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| {{ view_switch() }} | |||||
| {% if view == 'list' %} | {% if view == 'list' %} | ||||
| {% for tool in tools %} | |||||
| {{ resource_list(tool, loop, false) }} | |||||
| {% endfor %} | |||||
| {% else %} | |||||
| {% for tool in tools %} | |||||
| {{ resource_with_related(tool, loop, false) }} | |||||
| {% endfor %} | |||||
| {% endif %} | |||||
| {% if view == 'list' %} | |||||
| {% for book in books %} | |||||
| {{ resource_list(book, loop, false) }} | |||||
| {% endfor %} | |||||
| {% for resource in resources %} | |||||
| {{ resource_list(resource, loop, false) }} | |||||
| {% endfor %} | |||||
| {% else %} | {% else %} | ||||
| {% for book in books %} | |||||
| {{ resource_with_related(book, loop, false) }} | |||||
| {% endfor %} | |||||
| {% for resource in resources %} | |||||
| {{ resource_with_related(resource, loop, false) }} | |||||
| {% endfor %} | |||||
| {% endif %} | {% endif %} | ||||
| </div> | </div> | ||||
| {% endblock %} | |||||
| {% endblock %} |
| </div> | </div> | ||||
| </div> --> | </div> --> | ||||
| {% macro filter_dropdown(id, filter, plural='') %} | |||||
| <select name="{{ id }}" hx-trigger="change"> | |||||
| <option value="all" {% if request.args.get(id, '' ) == '' %} selected {% endif %} | |||||
| hx-get="{{ request.base_url }}?{% for key in request.args %}{% if key != id %}&{{ key }}={{ request.args.get(key) }}{% endif %}{% endfor %}" | |||||
| hx-push-url="true"> | |||||
| {% if plural != '' %} | |||||
| All {{ plural }} | |||||
| {% else %} | |||||
| All {{ id }}s | |||||
| {% endif%} | |||||
| </option> | |||||
| {% for thing in filter %} | |||||
| <option value="{{ thing[0] }}" {% if request.args.get(id)==thing[0]|string %} selected {% endif %} | |||||
| hx-get="{{ request.base_url }}?{{ id }}={{ thing[0] }}{% for key in request.args %}{% if key != id %}&{{ key }}={{ request.args.get(key) }}{% endif %}{% endfor %}" | |||||
| hx-push-url="true"> | |||||
| {{ thing[1] }} | |||||
| </option> | |||||
| {% endfor %} | |||||
| </select> | |||||
| {% endmacro%} | |||||
| {% macro filter_dropdown_nokey(id, filter, plural='') %} | |||||
| <select name="{{ id }}" hx-trigger="change"> | |||||
| <option value="all" {% if request.args.get(id, '' ) == '' %} selected {% endif %} | |||||
| hx-get="{{ request.base_url }}?{% for key in request.args %}{% if key != id %}&{{ key }}={{ request.args.get(key) }}{% endif %}{% endfor %}" | |||||
| hx-push-url="true"> | |||||
| {% if plural != '' %} | |||||
| All {{ plural }} | |||||
| {% else %} | |||||
| All {{ id }}s | |||||
| {% endif%} | |||||
| </option> | |||||
| {% for thing in filter %} | |||||
| <option value="{{ thing }}" {% if request.args.get(id)==thing|string %} selected {% endif %} | |||||
| hx-get="{{ request.base_url }}?{{ id }}={{ thing }}{% for key in request.args %}{% if key != id %}&{{ key }}={{ request.args.get(key) }}{% endif %}{% endfor %}" | |||||
| hx-push-url="true"> | |||||
| {{ thing }} | |||||
| </option> | |||||
| {% endfor %} | |||||
| </select> | |||||
| {% endmacro%} | |||||
| <div class="border-b-2 border-black grid lg:grid-cols-[52rem,30rem] content-start"> | <div class="border-b-2 border-black grid lg:grid-cols-[52rem,30rem] content-start"> | ||||
| <div class="mx-2 lg:ml-[13rem] text my-8 meta lg:max-w-[30rem]"> | <div class="mx-2 lg:ml-[13rem] text my-8 meta lg:max-w-[30rem]"> | ||||
| Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam ultricies egestas felis at dignissim. Morbi ut bibendum | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam ultricies egestas felis at dignissim. Morbi ut bibendum | ||||
| nisl. Integer ac sollicitudin risus. Vivamus et est est. Ut vitae lacus nec justo tincidunt interdum. Fusce sapien odio, | nisl. Integer ac sollicitudin risus. Vivamus et est est. Ut vitae lacus nec justo tincidunt interdum. Fusce sapien odio, | ||||
| commodo nec est et, interdum varius risus. Curabitur vehicula consequat auctor. | commodo nec est et, interdum varius risus. Curabitur vehicula consequat auctor. | ||||
| <br/><br/> | |||||
| <a href="{{ url_for(request.endpoint, view='list') }}">As list</a> <a href="{{ url_for(request.endpoint, view='') }}">With related</a> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| <script> | |||||
| function filter() { | |||||
| return { | |||||
| expandFilters: false, | |||||
| init() { | |||||
| // console.log(this.showRelated) | |||||
| } | |||||
| } | |||||
| } | |||||
| </script> | |||||
| <div class="" x-data="filter()"> | |||||
| <div id="resources" :class="expandFilters?'expanded':''"> | |||||
| <div class="std-margin grid lg:grid-cols-4 sticky top-14"> | |||||
| <div class="hidden lg:block cursor-pointer" @click="expandFilters = !expandFilters">Show/hide filters</div> | |||||
| <div class="" > | |||||
| <div id="resources" > | |||||
| {{ view_switch() }} | |||||
| <div class="flex gap-8"> | |||||
| {% if practices_filter %} | {% if practices_filter %} | ||||
| <div class=""> | |||||
| <div class="filter-header">Practices</div> | |||||
| <div class="filter-options my-4" x-show="expandFilters"> | |||||
| {% for practice in practices_filter %} | |||||
| <div {% if request.args.get('practice')==practice[0]|string %} class="active" {% endif %}> | |||||
| <a href="{{ url_for(request.endpoint, practice=practice[0]) }}" hx-target="#resources" hx-select="#resources">{{ practice[1] }}</a> | |||||
| </div> | |||||
| {% endfor %} | |||||
| </div> | |||||
| </div> | |||||
| {{ filter_dropdown('practice', practices_filter) }} | |||||
| {% endif %} | {% endif %} | ||||
| {% if year_filter %} | {% if year_filter %} | ||||
| <div class=""> | |||||
| <div class="filter-header">Year</div> | |||||
| <div class="filter-options my-4" x-show="expandFilters"> | |||||
| {% for year in year_filter %} | |||||
| <div {% if request.args.get('year')==year %} class="active" {% endif %}> | |||||
| <a href="{{ url_for(request.endpoint, year=year) }}" hx-target="#resources" hx-select="#resources">{{ year }}</a> | |||||
| </div> | |||||
| {% endfor %} | |||||
| </div> | |||||
| </div> | |||||
| {{ filter_dropdown_nokey('year', year_filter) }} | |||||
| {% endif %} | {% endif %} | ||||
| {% if typology_filter %} | {% if typology_filter %} | ||||
| <div class=""> | |||||
| <div class="filter-header">Typology category</div> | |||||
| <div class="filter-options my-4" x-show="expandFilters"> | |||||
| {% for typology in typology_filter %} | |||||
| <div {% if request.args.get('typology')==typology %} class="active" {% endif %}> | |||||
| <a href="{{ url_for(request.endpoint, typology=typology) }}" hx-target="#resources" hx-select="#resources">{{ typology }}</a> | |||||
| </div> | |||||
| {% endfor %} | |||||
| </div> | |||||
| </div> | |||||
| {{ filter_dropdown_nokey('typology', typology_filter, 'typologies') }} | |||||
| {% endif %} | {% endif %} | ||||
| {% if languages_filter %} | {% if languages_filter %} | ||||
| <div class="" > | |||||
| <div class="filter-header">Scripting languages</div> | |||||
| <div class="filter-options my-4" x-show="expandFilters"> | |||||
| {% for language in languages_filter %} | |||||
| <div {% if request.args.get('scriptingLanguage')==language %} class="active" {% endif %}> | |||||
| <a href="{{ url_for(request.endpoint, scriptingLanguage=language) }}" hx-target="#resources" hx-select="#resources">{{ language }}</a> | |||||
| </div> | |||||
| {% endfor %} | |||||
| </div> | |||||
| </div> | |||||
| {{ filter_dropdown_nokey('scriptingLanguage', languages_filter, 'scripting languages') }} | |||||
| {% endif %} | {% endif %} | ||||
| {% if licenses_filter %} | {% if licenses_filter %} | ||||
| <div class="" > | |||||
| <div class="filter-header">License</div> | |||||
| <div class="filter-options my-4" x-show="expandFilters"> | |||||
| {% for license in licenses_filter %} | |||||
| <div {% if request.args.get('license')==license %} class="active" {% endif %}> | |||||
| <a href="{{ url_for(request.endpoint, license=license) }}" hx-target="#resources" hx-select="#resources">{{ license }}</a> | |||||
| </div> | |||||
| {% endfor %} | |||||
| </div> | |||||
| </div> | |||||
| {{ filter_dropdown_nokey('license', licenses_filter) }} | |||||
| {% endif %} | {% endif %} | ||||
| {% if status_filter %} | {% if status_filter %} | ||||
| <div class="" > | |||||
| <div class="filter-header">Status</div> | |||||
| <div class="filter-options my-4" x-show="expandFilters"> | |||||
| {% for status in status_filter %} | |||||
| <div {% if request.args.get('status')==status %} class="active" {% endif %}> | |||||
| <a href="{{ url_for(request.endpoint, status=status) }}" hx-target="#resources" hx-select="#resources">{{ status }}</a> | |||||
| </div> | |||||
| {% endfor %} | |||||
| </div> | |||||
| </div> | |||||
| {{ filter_dropdown_nokey('status', status_filter, 'statuses') }} | |||||
| {% endif %} | {% endif %} | ||||
| </div> | |||||
| </div> | |||||
| <div> | |||||
| {% if view == 'list' %} | |||||
| {% for resource in resources %} | |||||
| {{ resource_list(resource, loop) }} | |||||
| {% endfor %} | |||||
| {% else %} | |||||
| {% for resource in resources %} | |||||
| {{ resource_with_related(resource, loop) }} | |||||
| {% endfor %} | |||||
| {% endif %} | |||||
| </div> | |||||
| <div> | |||||
| {% if view == 'list' %} | |||||
| {% for resource in resources %} | |||||
| {{ resource_list(resource, loop) }} | |||||
| {% endfor %} | |||||
| {% else %} | |||||
| {% for resource in resources %} | |||||
| {{ resource_with_related(resource, loop) }} | |||||
| {% endfor %} | |||||
| {% endif %} | |||||
| </div> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| @tool.route('/tools') | @tool.route('/tools') | ||||
| def get_tools(): | def get_tools(): | ||||
| view = request.args.get('view') | view = request.args.get('view') | ||||
| type = 'tool' | |||||
| tools = Resource.query.filter_by(type=type).all() | |||||
| resource_type = 'tool' | |||||
| tools_query = Resource.query.filter_by(type=resource_type) | |||||
| for key in request.args.keys(): | for key in request.args.keys(): | ||||
| if key != 'view': | if key != 'view': | ||||
| if key == 'practice': | if key == 'practice': | ||||
| tools = Resource.query.join(Relationship, Relationship.first_resource_id == Resource.id, isouter=True).filter(Resource.type==type, Relationship.second_resource_id==request.args.get(key)).all() | |||||
| also_tools = Resource.query.join(Relationship, Relationship.second_resource_id == Resource.id, isouter=True).filter(Resource.type==type, Relationship.first_resource_id==request.args.get(key)).all() | |||||
| tools = tools + also_tools | |||||
| elif key == 'scriptingLanguage': | |||||
| tools_1 = tools_query.join(Relationship, Relationship.first_resource_id == Resource.id, isouter=True).filter(Relationship.second_resource_id==request.args.get(key)) | |||||
| tools_2 = tools_query.join(Relationship, Relationship.second_resource_id == Resource.id, isouter=True).filter(Relationship.first_resource_id==request.args.get(key)) | |||||
| tools_query = tools_1.union(tools_2) | |||||
| if key == 'scriptingLanguage': | |||||
| regex = request.args.get(key) + "$|" + request.args.get(key) + "\s\/" | regex = request.args.get(key) + "$|" + request.args.get(key) + "\s\/" | ||||
| tools = Resource.query.filter_by(type=type).filter(Resource.scriptingLanguage.regexp_match(regex)).all() | |||||
| else: | |||||
| kwargs = {'type': type, key: request.args.get(key)} | |||||
| tools = Resource.query.filter_by(**kwargs).all() | |||||
| tools_query = tools_query.filter(Resource.scriptingLanguage.regexp_match(regex)) | |||||
| if key != 'practice' and key != 'scriptingLanguage': | |||||
| kwargs = {key: request.args.get(key)} | |||||
| tools_query = tools_query.filter_by(**kwargs) | |||||
| # finalise the query | |||||
| tools = tools_query.all() | |||||
| # get number of tools | # get number of tools | ||||
| count = len(tools) | count = len(tools) | ||||
| if view != 'list': | if view != 'list': | ||||
| # append relationships to each tool | # append relationships to each tool | ||||
| append_relationships_multiple(tools) | append_relationships_multiple(tools) | ||||
| # get filters | |||||
| else: | |||||
| # reorder tools by tools name | |||||
| tools = sorted(tools, key=lambda d: d.__dict__['name']) | |||||
| # get values for filters | |||||
| # practices | # practices | ||||
| practices_filter = Resource.query.filter_by(type='practice').with_entities(Resource.id, Resource.name) | |||||
| #FOR LATER: SELECT Resource.name, second.name FROM Resource LEFT JOIN Relationship ON Resource.id=Relationship.first_resource_id LEFT JOIN Resource second ON Relationship.second_resource_id=second.id; | |||||
| practices_filter = Resource.query.filter_by(type='practice').with_entities(Resource.id, Resource.name).all() | |||||
| # license | # license | ||||
| licenses_filter = get_filter_values('license', type) | |||||
| licenses_filter = get_filter_values('license', resource_type) | |||||
| # language | # language | ||||
| languages_filter = get_filter_values('scriptingLanguage', type) | |||||
| languages_filter = get_filter_values('scriptingLanguage', resource_type) | |||||
| # status | # status | ||||
| status_filter = get_filter_values('status', type) | |||||
| return render_template('resources.html', resources=tools, type=type, practices_filter=practices_filter, licenses_filter=licenses_filter, languages_filter=languages_filter, status_filter=status_filter, count=count, view=view) | |||||
| status_filter = get_filter_values('status', resource_type) | |||||
| return render_template('resources.html', resources=tools, type=resource_type, practices_filter=practices_filter, licenses_filter=licenses_filter, languages_filter=languages_filter, status_filter=status_filter, count=count, view=view) | |||||
| # route for displaying a single tool based on the ID in the database | # route for displaying a single tool based on the ID in the database | ||||
| @tool.route('/tools/<int:tool_id>') | @tool.route('/tools/<int:tool_id>') |