mirror of
https://github.com/logos-co/open-law.git
synced 2025-02-12 23:06:30 +00:00
working on
This commit is contained in:
parent
75c0b6b3a8
commit
d8d0db943d
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
@ -13,6 +13,7 @@
|
||||
"cSpell.words": [
|
||||
"bookname",
|
||||
"Btns",
|
||||
"CLEANR",
|
||||
"flowbite",
|
||||
"jsonify",
|
||||
"pydantic",
|
||||
|
@ -26,6 +26,7 @@ def create_app(environment="development"):
|
||||
vote_blueprint,
|
||||
approve_blueprint,
|
||||
star_blueprint,
|
||||
search_blueprint,
|
||||
)
|
||||
from app.models import (
|
||||
User,
|
||||
@ -57,6 +58,7 @@ def create_app(environment="development"):
|
||||
app.register_blueprint(vote_blueprint)
|
||||
app.register_blueprint(approve_blueprint)
|
||||
app.register_blueprint(star_blueprint)
|
||||
app.register_blueprint(search_blueprint)
|
||||
|
||||
# Set up flask login.
|
||||
@login_manager.user_loader
|
||||
|
@ -2,3 +2,4 @@
|
||||
from .pagination import create_pagination
|
||||
from .breadcrumbs import create_breadcrumbs
|
||||
from .book_verify import register_book_verify_route, book_validator
|
||||
from .clean_html import clean_html
|
||||
|
9
app/controllers/clean_html.py
Normal file
9
app/controllers/clean_html.py
Normal file
@ -0,0 +1,9 @@
|
||||
import re
|
||||
|
||||
# as per recommendation from @freylis, compile once only
|
||||
CLEANR = re.compile("<.*?>")
|
||||
|
||||
|
||||
def clean_html(raw_html):
|
||||
clean_text = re.sub(CLEANR, "", raw_html)
|
||||
return clean_text
|
@ -13,4 +13,3 @@ from .interpretation import CreateInterpretationForm, EditInterpretationForm
|
||||
from .comment import CreateCommentForm
|
||||
from .vote import VoteForm
|
||||
from .comment import CreateCommentForm, DeleteCommentForm, EditCommentForm
|
||||
from .search import SearchForm
|
||||
|
@ -1,8 +0,0 @@
|
||||
from flask_wtf import FlaskForm
|
||||
from wtforms import StringField, SubmitField
|
||||
from wtforms.validators import DataRequired
|
||||
|
||||
|
||||
class SearchForm(FlaskForm):
|
||||
search_query = StringField("SearchQuery", [DataRequired()])
|
||||
submit = SubmitField("Submit")
|
@ -8,6 +8,7 @@ class Interpretation(BaseModel):
|
||||
__tablename__ = "interpretations"
|
||||
|
||||
text = db.Column(db.Text, unique=False, nullable=False)
|
||||
plain_text = db.Column(db.Text, unique=False)
|
||||
approved = db.Column(db.Boolean, default=False)
|
||||
marked = db.Column(db.Boolean, default=False)
|
||||
|
||||
|
@ -1483,6 +1483,14 @@ input:checked + .toggle-bg {
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.h-2 {
|
||||
height: 0.5rem;
|
||||
}
|
||||
|
||||
.h-2\.5 {
|
||||
height: 0.625rem;
|
||||
}
|
||||
|
||||
.max-h-40 {
|
||||
max-height: 10rem;
|
||||
}
|
||||
@ -1583,6 +1591,14 @@ input:checked + .toggle-bg {
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
.w-2 {
|
||||
width: 0.5rem;
|
||||
}
|
||||
|
||||
.w-2\.5 {
|
||||
width: 0.625rem;
|
||||
}
|
||||
|
||||
.max-w-2xl {
|
||||
max-width: 42rem;
|
||||
}
|
||||
@ -2133,6 +2149,11 @@ input:checked + .toggle-bg {
|
||||
background-color: rgb(255 255 255 / 0.5);
|
||||
}
|
||||
|
||||
.bg-green-500 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(14 159 110 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-opacity-50 {
|
||||
--tw-bg-opacity: 0.5;
|
||||
}
|
||||
@ -2612,6 +2633,11 @@ input:checked + .toggle-bg {
|
||||
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.hover\:bg-gray-50:hover {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(249 250 251 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.hover\:bg-gradient-to-bl:hover {
|
||||
background-image: linear-gradient(to bottom left, var(--tw-gradient-stops));
|
||||
}
|
||||
@ -2646,6 +2672,10 @@ input:checked + .toggle-bg {
|
||||
color: rgb(255 255 255 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.hover\:underline:hover {
|
||||
text-decoration-line: underline;
|
||||
}
|
||||
|
||||
.focus\:border-blue-500:focus {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(63 131 248 / var(--tw-border-opacity));
|
||||
@ -2734,6 +2764,11 @@ input:checked + .toggle-bg {
|
||||
color: rgb(17 24 39 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.group:hover .group-hover\:text-gray-500 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(107 114 128 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.peer:-moz-placeholder-shown ~ .peer-placeholder-shown\:translate-y-0 {
|
||||
--tw-translate-y: 0px;
|
||||
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
||||
@ -2974,6 +3009,10 @@ input:checked + .toggle-bg {
|
||||
--tw-shadow: var(--tw-shadow-colored);
|
||||
}
|
||||
|
||||
:is(.dark .dark\:ring-offset-gray-800) {
|
||||
--tw-ring-offset-color: #1F2937;
|
||||
}
|
||||
|
||||
:is(.dark .dark\:hover\:border-gray-600:hover) {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(75 85 99 / var(--tw-border-opacity));
|
||||
@ -3099,11 +3138,25 @@ input:checked + .toggle-bg {
|
||||
--tw-ring-color: rgb(5 80 92 / var(--tw-ring-opacity));
|
||||
}
|
||||
|
||||
:is(.dark .dark\:focus\:ring-blue-600:focus) {
|
||||
--tw-ring-opacity: 1;
|
||||
--tw-ring-color: rgb(28 100 242 / var(--tw-ring-opacity));
|
||||
}
|
||||
|
||||
:is(.dark .dark\:focus\:ring-offset-gray-800:focus) {
|
||||
--tw-ring-offset-color: #1F2937;
|
||||
}
|
||||
|
||||
:is(.dark .group:hover .dark\:group-hover\:text-white) {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(255 255 255 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
:is(.dark .group:hover .dark\:group-hover\:text-gray-300) {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(209 213 219 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.peer:focus ~ :is(.dark .peer-focus\:dark\:text-blue-500) {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(63 131 248 / var(--tw-text-opacity));
|
||||
|
File diff suppressed because one or more lines are too long
@ -1,124 +0,0 @@
|
||||
<!-- prettier-ignore -->
|
||||
{% extends 'base.html' %}
|
||||
{% block content %}
|
||||
<div class="border-b border-gray-200 dark:border-gray-700 md:mr-64">
|
||||
<!-- prettier-ignore -->
|
||||
<h1 class="hidden md:inline font-extrabold text-lg dark:text-white ml-4 mt-5">Search results</h1>
|
||||
<!-- prettier-ignore -->
|
||||
<p class="hidden md:block text-sm ml-4 w-1/2 text-gray-500 text-center md:text-left dark:text-gray-400"> Search result for {{query}} </p>
|
||||
<!-- prettier-ignore -->
|
||||
<p class="hidden md:block text-sm ml-4 w-1/2 text-gray-500 text-center md:text-left dark:text-gray-400"> Showing 35 results </p>
|
||||
<!-- prettier-ignore -->
|
||||
<ul class="flex md:flex-wrap -mb-px text-xs md:text-sm font-medium text-center" id="myTab" data-tabs-toggle="#myTabContent" role="tablist">
|
||||
<li class="mr-2 w-full md:w-auto" role="presentation">
|
||||
<!-- prettier-ignore -->
|
||||
<button class="inline-flex p-4 border-b-2 rounded-t-lg" id="interpretations-tab" data-tabs-target="#interpretations" type="button" role="tab" aria-controls="interpretations" aria-selected="false"> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6 mr-3"> <path stroke-linecap="round" stroke-linejoin="round" d="M3.75 13.5l10.5-11.25L12 10.5h8.25L9.75 21.75 12 13.5H3.75z" /> </svg>
|
||||
Interpretations
|
||||
</button>
|
||||
</li>
|
||||
<li class="mr-2 w-full md:w-auto" role="presentation">
|
||||
<!-- prettier-ignore -->
|
||||
<button class="inline-flex p-4 border-b-2 border-transparent rounded-t-lg hover:text-gray-600 hover:border-gray-300 dark:hover:text-gray-300" id="books-tab" data-tabs-target="#books" type="button" role="tab" aria-controls="books" aria-selected="false"> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6 mr-3"> <path stroke-linecap="round" stroke-linejoin="round" d="M16.5 3.75V16.5L12 14.25 7.5 16.5V3.75m9 0H18A2.25 2.25 0 0120.25 6v12A2.25 2.25 0 0118 20.25H6A2.25 2.25 0 013.75 18V6A2.25 2.25 0 016 3.75h1.5m9 0h-9" /> </svg>
|
||||
Books
|
||||
</button>
|
||||
</li>
|
||||
<li class="mr-2 w-full md:w-auto" role="presentation">
|
||||
<!-- prettier-ignore -->
|
||||
<button class="inline-flex p-4 border-b-2 border-transparent rounded-t-lg hover:text-gray-600 hover:border-gray-300 dark:hover:text-gray-300" id="users-tab" data-tabs-target="#users" type="button" role="tab" aria-controls="users" aria-selected="false"> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6 mr-3"> <path stroke-linecap="round" stroke-linejoin="round" d="M17.982 18.725A7.488 7.488 0 0012 15.75a7.488 7.488 0 00-5.982 2.975m11.963 0a9 9 0 10-11.963 0m11.963 0A8.966 8.966 0 0112 21a8.966 8.966 0 01-5.982-2.275M15 9.75a3 3 0 11-6 0 3 3 0 016 0z" /> </svg>
|
||||
Users
|
||||
</button>
|
||||
</li>
|
||||
<li class="mr-2 w-full md:w-auto" role="presentation">
|
||||
<!-- prettier-ignore -->
|
||||
<button class="inline-flex p-4 border-b-2 border-transparent rounded-t-lg hover:text-gray-600 hover:border-gray-300 dark:hover:text-gray-300" id="tags-tab" data-tabs-target="#tags" type="button" role="tab" aria-controls="tags" aria-selected="false"> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6 mr-3"> <path stroke-linecap="round" stroke-linejoin="round" d="M9.568 3H5.25A2.25 2.25 0 003 5.25v4.318c0 .597.237 1.17.659 1.591l9.581 9.581c.699.699 1.78.872 2.607.33a18.095 18.095 0 005.223-5.223c.542-.827.369-1.908-.33-2.607L11.16 3.66A2.25 2.25 0 009.568 3z" /> <path stroke-linecap="round" stroke-linejoin="round" d="M6 6h.008v.008H6V6z" /> </svg>
|
||||
Tags
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="myTabContent" class="md:mr-64">
|
||||
<!-- prettier-ignore -->
|
||||
<div class="hidden p-4 rounded-lg bg-gray-50 dark:bg-gray-800" id="interpretations" role="tabpanel" aria-labelledby="interpretations-tab">
|
||||
{% for interpretation in interpretations %}
|
||||
<!-- prettier-ignore -->
|
||||
<dl class="bg-white dark:bg-gray-900 max-w-full p-3 text-gray-900 divide-y divide-gray-200 dark:text-white dark:divide-gray-700 m-3 border-2 border-gray-200 border-solid rounded-lg dark:border-gray-700">
|
||||
<div class="flex flex-row pb-3 p-3 w-2/3 md:w-10/12">
|
||||
<div class="vote-block flex flex-col m-5 justify-center items-center">
|
||||
{% if interpretation.user_id != current_user.id %}
|
||||
<div class="vote-button cursor-pointer" data-vote-for="interpretation" data-entity-id="{{ interpretation.id }}" data-positive="true">
|
||||
<svg class="w-6 h-6 select-none
|
||||
{% if interpretation.current_user_vote %}
|
||||
stroke-green-500
|
||||
{% endif %}
|
||||
" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" > <path stroke-linecap="round" stroke-linejoin="round" d="M4.5 10.5L12 3m0 0l7.5 7.5M12 3v18" /> </svg>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<span
|
||||
class="vote-count text-3xl select-none
|
||||
{% if interpretation.vote_count < 0 %}
|
||||
text-red-500
|
||||
{% elif interpretation.vote_count > 0 %}
|
||||
text-green-500
|
||||
{% endif %}
|
||||
"
|
||||
>
|
||||
{{ interpretation.vote_count }}
|
||||
</span>
|
||||
|
||||
{% if interpretation.user_id != current_user.id %}
|
||||
<div class="vote-button cursor-pointer" data-vote-for="interpretation" data-entity-id="{{ interpretation.id }}" data-positive="false">
|
||||
<svg class="w-6 h-6 select-none
|
||||
{% if interpretation.current_user_vote == False %}
|
||||
stroke-red-500
|
||||
{% endif %}
|
||||
" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M19.5 13.5L12 21m0 0l-7.5-7.5M12 21V3" /> </svg>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<!-- prettier-ignore -->
|
||||
<dt class="flex w-full mb-1 text-gray-500 md:text-lg dark:text-gray-400 flex-col">
|
||||
<div class="ql-snow truncate md:max-w-xl">
|
||||
{% set local_breadcrumbs = interpretation.section.breadcrumbs_path %}
|
||||
{% include 'book/local_breadcrumbs_navigation.html'%}
|
||||
<p>{{ interpretation.section.label }}</p>
|
||||
</a>
|
||||
<div class="dark:text-white h-30 ql-editor-readonly">
|
||||
<p>{{ interpretation.text|safe }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex mt-auto align-center justify-between md:w-full">
|
||||
<div>
|
||||
<span class="hidden md:inline-block">Interpretation by</span>
|
||||
<a href="{{url_for('user.profile',user_id=interpretation.user.id)}}" class=" text-blue-500 {% if interpretation.user.is_deleted %}line-through{% endif %}">{{interpretation.user.username}}</a> on {{interpretation.created_at.strftime('%B %d, %Y')}}
|
||||
</div>
|
||||
<div class="flex ml-auto justify-between w-24">
|
||||
<button data-tooltip-target="tooltip-click" data-tooltip-trigger="click" id="copyLinkButton" type="button" class="hover:text-white focus:ring-2 rounded-full font-medium text-sm p-2.5 text-center inline-flex items-center dark:hover:text-white" data-link="{{ build_qa_url(interpretation) }}">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6"> <path stroke-linecap="round" stroke-linejoin="round" d="M9 8.25H7.5a2.25 2.25 0 00-2.25 2.25v9a2.25 2.25 0 002.25 2.25h9a2.25 2.25 0 002.25-2.25v-9a2.25 2.25 0 00-2.25-2.25H15m0-3l-3-3m0 0l-3 3m3-3V15" /> </svg>
|
||||
</button>
|
||||
<div id="tooltip-click" role="tooltip" class="absolute z-10 invisible inline-block px-3 py-2 text-sm font-medium text-white bg-gray-900 rounded-lg shadow-sm opacity-0 tooltip dark:bg-gray-700"> Link copied! <div class="tooltip-arrow" data-popper-arrow></div> </div>
|
||||
<div class="space-x-0.5 flex items-center">
|
||||
<a class="!cursor-pointer text-no-underline flex items-center" href="{{ build_qa_url(interpretation) }}" >
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6"> <path stroke-linecap="round" stroke-linejoin="round" d="M20.25 8.511c.884.284 1.5 1.128 1.5 2.097v4.286c0 1.136-.847 2.1-1.98 2.193-.34.027-.68.052-1.02.072v3.091l-3-3c-1.354 0-2.694-.055-4.02-.163a2.115 2.115 0 01-.825-.242m9.345-8.334a2.126 2.126 0 00-.476-.095 48.64 48.64 0 00-8.048 0c-1.131.094-1.976 1.057-1.976 2.192v4.286c0 .837.46 1.58 1.155 1.951m9.345-8.334V6.637c0-1.621-1.152-3.026-2.76-3.235A48.455 48.455 0 0011.25 3c-2.115 0-4.198.137-6.24.402-1.608.209-2.76 1.614-2.76 3.235v6.226c0 1.621 1.152 3.026 2.76 3.235.577.075 1.157.14 1.74.194V21l4.155-4.155" /> </svg>
|
||||
<p>{{interpretation.active_comments | length}}</p>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</dt>
|
||||
</div>
|
||||
</dl>
|
||||
|
||||
{% endfor %}
|
||||
</div>
|
||||
<!-- prettier-ignore -->
|
||||
<div class="hidden p-4 rounded-lg bg-gray-50 dark:bg-gray-800" id="books" role="tabpanel" aria-labelledby="books-tab">
|
||||
</div>
|
||||
<!-- prettier-ignore -->
|
||||
<div class="hidden p-4 rounded-lg bg-gray-50 dark:bg-gray-800" id="users" role="tabpanel" aria-labelledby="users-tab">
|
||||
</div>
|
||||
<!-- prettier-ignore -->
|
||||
<div class="hidden p-4 rounded-lg bg-gray-50 dark:bg-gray-800" id="tags" role="tabpanel" aria-labelledby="tags-tab">
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
49
app/templates/searchResultsBooks.html
Normal file
49
app/templates/searchResultsBooks.html
Normal file
@ -0,0 +1,49 @@
|
||||
<!-- prettier-ignore -->
|
||||
{% extends 'base.html' %}
|
||||
{% block content %}
|
||||
<div class="border-b border-gray-200 dark:border-gray-700 md:mr-64">
|
||||
<!-- prettier-ignore -->
|
||||
<h1 class="hidden md:inline font-extrabold text-lg dark:text-white ml-4 mt-5">Search results</h1>
|
||||
<!-- prettier-ignore -->
|
||||
<p class="hidden md:block text-sm ml-4 w-1/2 text-gray-500 text-center md:text-left dark:text-gray-400"> Search result for {{query}} </p>
|
||||
<!-- prettier-ignore -->
|
||||
<p class="hidden md:block text-sm ml-4 w-1/2 text-gray-500 text-center md:text-left dark:text-gray-400"> Showing {{count}} results </p>
|
||||
<!-- prettier-ignore -->
|
||||
<div class="border-b border-gray-200 dark:border-gray-700">
|
||||
<ul class="flex flex-wrap -mb-px text-sm font-medium text-center text-gray-500 dark:text-gray-400">
|
||||
<li class="mr-2">
|
||||
<a href="{{url_for('search.search_interpretations',q=query)}}" class="inline-flex p-4 border-b-2 border-transparent rounded-t-lg hover:text-gray-600 hover:border-gray-300 dark:hover:text-gray-300 group" >
|
||||
<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 mr-2 text-gray-400 group-hover:text-gray-500 dark:text-gray-500 dark:group-hover:text-gray-300" fill="currentColor" viewBox="0 0 24 24" stroke-width="1.5" > <path stroke-linecap="round" stroke-linejoin="round" d="M3.75 13.5l10.5-11.25L12 10.5h8.25L9.75 21.75 12 13.5H3.75z" /> </svg>
|
||||
Interpretations
|
||||
</a>
|
||||
</li>
|
||||
<li class="mr-2">
|
||||
<a class="inline-flex p-4 text-blue-600 border-b-2 border-blue-600 rounded-t-lg active dark:text-blue-500 dark:border-blue-500 group" aria-current="page">
|
||||
<svg aria-hidden="true" class="w-5 h-5 mr-2 text-blue-600 dark:text-blue-500" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M16.5 3.75V16.5L12 14.25 7.5 16.5V3.75m9 0H18A2.25 2.25 0 0120.25 6v12A2.25 2.25 0 0118 20.25H6A2.25 2.25 0 013.75 18V6A2.25 2.25 0 016 3.75h1.5m9 0h-9" /> </svg>
|
||||
Books
|
||||
</a>
|
||||
</li>
|
||||
<li class="mr-2">
|
||||
<a href="{{url_for('search.search_users', q=query) }}" class="inline-flex p-4 border-b-2 border-transparent rounded-t-lg hover:text-gray-600 hover:border-gray-300 dark:hover:text-gray-300 group">
|
||||
<svg aria-hidden="true" class="w-5 h-5 mr-2 text-gray-400 group-hover:text-gray-500 dark:text-gray-500 dark:group-hover:text-gray-300" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M17.982 18.725A7.488 7.488 0 0012 15.75a7.488 7.488 0 00-5.982 2.975m11.963 0a9 9 0 10-11.963 0m11.963 0A8.966 8.966 0 0112 21a8.966 8.966 0 01-5.982-2.275M15 9.75a3 3 0 11-6 0 3 3 0 016 0z" /> </svg>
|
||||
Users
|
||||
</a>
|
||||
</li>
|
||||
<li class="mr-2">
|
||||
<a href="{{url_for('search.search_tags',q=query)}}" class="inline-flex p-4 border-b-2 border-transparent rounded-t-lg hover:text-gray-600 hover:border-gray-300 dark:hover:text-gray-300 group">
|
||||
<svg aria-hidden="true" class="w-5 h-5 mr-2 text-gray-400 group-hover:text-gray-500 dark:text-gray-500 dark:group-hover:text-gray-300" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M9.568 3H5.25A2.25 2.25 0 003 5.25v4.318c0 .597.237 1.17.659 1.591l9.581 9.581c.699.699 1.78.872 2.607.33a18.095 18.095 0 005.223-5.223c.542-.827.369-1.908-.33-2.607L11.16 3.66A2.25 2.25 0 009.568 3z" /> <path stroke-linecap="round" stroke-linejoin="round" d="M6 6h.008v.008H6V6z" /> </svg>
|
||||
Tags
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<!-- prettier-ignore -->
|
||||
<div class="md:mr-64 p-4 rounded-lg bg-gray-50 dark:bg-gray-800" id="books" role="tabpanel" aria-labelledby="books-tab">
|
||||
{% if count<1 %}
|
||||
{% else %}
|
||||
<h1 class="hidden md:inline font-extrabold text-lg dark:text-white ml-4 mt-5">No {{query}} in any book name or included content, try another search query.</h1>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
119
app/templates/searchResultsInterpretations.html
Normal file
119
app/templates/searchResultsInterpretations.html
Normal file
@ -0,0 +1,119 @@
|
||||
<!-- prettier-ignore -->
|
||||
{% extends 'base.html' %}
|
||||
{% block content %}
|
||||
<div class="border-b border-gray-200 dark:border-gray-700 md:mr-64">
|
||||
<!-- prettier-ignore -->
|
||||
<h1 class="hidden md:inline font-extrabold text-lg dark:text-white ml-4 mt-5">Search results</h1>
|
||||
<!-- prettier-ignore -->
|
||||
<p class="hidden md:block text-sm ml-4 w-1/2 text-gray-500 text-center md:text-left dark:text-gray-400"> Search result for {{query}} </p>
|
||||
<!-- prettier-ignore -->
|
||||
<p class="hidden md:block text-sm ml-4 w-1/2 text-gray-500 text-center md:text-left dark:text-gray-400"> Showing {{count}} results </p>
|
||||
<!-- prettier-ignore -->
|
||||
<div class="border-b border-gray-200 dark:border-gray-700">
|
||||
<ul class="flex flex-wrap -mb-px text-sm font-medium text-center text-gray-500 dark:text-gray-400">
|
||||
<li class="mr-2">
|
||||
<a class="inline-flex p-4 text-blue-600 border-b-2 border-blue-600 rounded-t-lg active dark:text-blue-500 dark:border-blue-500 group" aria-current="page">
|
||||
<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 24 24" stroke-width="1.5" class="w-5 h-5 mr-2 text-blue-600 dark:text-blue-500"> <path stroke-linecap="round" stroke-linejoin="round" d="M3.75 13.5l10.5-11.25L12 10.5h8.25L9.75 21.75 12 13.5H3.75z" /> </svg>
|
||||
Interpretations
|
||||
</a>
|
||||
</li>
|
||||
<li class="mr-2">
|
||||
<a href="{{url_for('search.search_books',q=query)}}" class="inline-flex p-4 border-b-2 border-transparent rounded-t-lg hover:text-gray-600 hover:border-gray-300 dark:hover:text-gray-300 group" >
|
||||
<svg aria-hidden="true" class="w-5 h-5 mr-2 text-gray-400 group-hover:text-gray-500 dark:text-gray-500 dark:group-hover:text-gray-300" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M16.5 3.75V16.5L12 14.25 7.5 16.5V3.75m9 0H18A2.25 2.25 0 0120.25 6v12A2.25 2.25 0 0118 20.25H6A2.25 2.25 0 013.75 18V6A2.25 2.25 0 016 3.75h1.5m9 0h-9" /> </svg>
|
||||
Books
|
||||
</a>
|
||||
</li>
|
||||
<li class="mr-2">
|
||||
<a href="{{url_for('search.search_users', q=query) }}" class="inline-flex p-4 border-b-2 border-transparent rounded-t-lg hover:text-gray-600 hover:border-gray-300 dark:hover:text-gray-300 group">
|
||||
<svg aria-hidden="true" class="w-5 h-5 mr-2 text-gray-400 group-hover:text-gray-500 dark:text-gray-500 dark:group-hover:text-gray-300" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M17.982 18.725A7.488 7.488 0 0012 15.75a7.488 7.488 0 00-5.982 2.975m11.963 0a9 9 0 10-11.963 0m11.963 0A8.966 8.966 0 0112 21a8.966 8.966 0 01-5.982-2.275M15 9.75a3 3 0 11-6 0 3 3 0 016 0z" /> </svg>
|
||||
Users
|
||||
</a>
|
||||
</li>
|
||||
<li class="mr-2">
|
||||
<a href="{{url_for('search.search_tags',q=query)}}" class="inline-flex p-4 border-b-2 border-transparent rounded-t-lg hover:text-gray-600 hover:border-gray-300 dark:hover:text-gray-300 group">
|
||||
<svg aria-hidden="true" class="w-5 h-5 mr-2 text-gray-400 group-hover:text-gray-500 dark:text-gray-500 dark:group-hover:text-gray-300" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M9.568 3H5.25A2.25 2.25 0 003 5.25v4.318c0 .597.237 1.17.659 1.591l9.581 9.581c.699.699 1.78.872 2.607.33a18.095 18.095 0 005.223-5.223c.542-.827.369-1.908-.33-2.607L11.16 3.66A2.25 2.25 0 009.568 3z" /> <path stroke-linecap="round" stroke-linejoin="round" d="M6 6h.008v.008H6V6z" /> </svg>
|
||||
Tags
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<!-- prettier-ignore -->
|
||||
<div class="md:mr-64 p-4 rounded-lg bg-gray-50 dark:bg-gray-800" id="interpretations" role="tabpanel" aria-labelledby="interpretations-tab">
|
||||
{% if count <1 %}
|
||||
<h1 class="hidden md:inline font-extrabold text-lg dark:text-white ml-4 mt-5">No {{query}} in any interpretation, try another search query.</h1>
|
||||
{% else %}
|
||||
{% for interpretation in interpretations %}
|
||||
<!-- prettier-ignore -->
|
||||
<dl class="bg-white dark:bg-gray-900 max-w-full p-3 text-gray-900 divide-y divide-gray-200 dark:text-white dark:divide-gray-700 m-3 border-2 border-gray-200 border-solid rounded-lg dark:border-gray-700">
|
||||
<div class="flex flex-row pb-3 p-3 w-2/3 md:w-10/12">
|
||||
<div class="vote-block flex flex-col m-5 justify-center items-center">
|
||||
{% if interpretation.user_id != current_user.id %}
|
||||
<div class="vote-button cursor-pointer" data-vote-for="interpretation" data-entity-id="{{ interpretation.id }}" data-positive="true">
|
||||
<svg class="w-6 h-6 select-none
|
||||
{% if interpretation.current_user_vote %}
|
||||
stroke-green-500
|
||||
{% endif %}
|
||||
" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" > <path stroke-linecap="round" stroke-linejoin="round" d="M4.5 10.5L12 3m0 0l7.5 7.5M12 3v18" /> </svg>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<span
|
||||
class="vote-count text-3xl select-none
|
||||
{% if interpretation.vote_count < 0 %}
|
||||
text-red-500
|
||||
{% elif interpretation.vote_count > 0 %}
|
||||
text-green-500
|
||||
{% endif %}
|
||||
"
|
||||
>
|
||||
{{ interpretation.vote_count }}
|
||||
</span>
|
||||
|
||||
{% if interpretation.user_id != current_user.id %}
|
||||
<div class="vote-button cursor-pointer" data-vote-for="interpretation" data-entity-id="{{ interpretation.id }}" data-positive="false">
|
||||
<svg class="w-6 h-6 select-none
|
||||
{% if interpretation.current_user_vote == False %}
|
||||
stroke-red-500
|
||||
{% endif %}
|
||||
" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M19.5 13.5L12 21m0 0l-7.5-7.5M12 21V3" /> </svg>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<!-- prettier-ignore -->
|
||||
<dt class="flex w-full mb-1 text-gray-500 md:text-lg dark:text-gray-400 flex-col">
|
||||
<div class="ql-snow md:max-w-xl">
|
||||
{% set local_breadcrumbs = interpretation.section.breadcrumbs_path %}
|
||||
{% include 'book/local_breadcrumbs_navigation.html'%}
|
||||
<p>{{ interpretation.section.label }}</p>
|
||||
</a>
|
||||
<div class="dark:text-white h-30 ql-editor-readonly">
|
||||
<p>{{ interpretation.text|safe }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex mt-auto align-center justify-between md:w-full">
|
||||
<div>
|
||||
<span class="hidden md:inline-block">Interpretation by</span>
|
||||
<a href="{{url_for('user.profile',user_id=interpretation.user.id)}}" class=" text-blue-500 {% if interpretation.user.is_deleted %}line-through{% endif %}">{{interpretation.user.username}}</a> on {{interpretation.created_at.strftime('%B %d, %Y')}}
|
||||
</div>
|
||||
<div class="flex ml-auto justify-between w-24">
|
||||
<button data-tooltip-target="tooltip-click" data-tooltip-trigger="click" id="copyLinkButton" type="button" class="hover:text-white focus:ring-2 rounded-full font-medium text-sm p-2.5 text-center inline-flex items-center dark:hover:text-white" data-link="{{ build_qa_url(interpretation) }}">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6"> <path stroke-linecap="round" stroke-linejoin="round" d="M9 8.25H7.5a2.25 2.25 0 00-2.25 2.25v9a2.25 2.25 0 002.25 2.25h9a2.25 2.25 0 002.25-2.25v-9a2.25 2.25 0 00-2.25-2.25H15m0-3l-3-3m0 0l-3 3m3-3V15" /> </svg>
|
||||
</button>
|
||||
<div id="tooltip-click" role="tooltip" class="absolute z-10 invisible inline-block px-3 py-2 text-sm font-medium text-white bg-gray-900 rounded-lg shadow-sm opacity-0 tooltip dark:bg-gray-700"> Link copied! <div class="tooltip-arrow" data-popper-arrow></div> </div>
|
||||
<div class="space-x-0.5 flex items-center">
|
||||
<a class="!cursor-pointer text-no-underline flex items-center" href="{{ build_qa_url(interpretation) }}" >
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6"> <path stroke-linecap="round" stroke-linejoin="round" d="M20.25 8.511c.884.284 1.5 1.128 1.5 2.097v4.286c0 1.136-.847 2.1-1.98 2.193-.34.027-.68.052-1.02.072v3.091l-3-3c-1.354 0-2.694-.055-4.02-.163a2.115 2.115 0 01-.825-.242m9.345-8.334a2.126 2.126 0 00-.476-.095 48.64 48.64 0 00-8.048 0c-1.131.094-1.976 1.057-1.976 2.192v4.286c0 .837.46 1.58 1.155 1.951m9.345-8.334V6.637c0-1.621-1.152-3.026-2.76-3.235A48.455 48.455 0 0011.25 3c-2.115 0-4.198.137-6.24.402-1.608.209-2.76 1.614-2.76 3.235v6.226c0 1.621 1.152 3.026 2.76 3.235.577.075 1.157.14 1.74.194V21l4.155-4.155" /> </svg>
|
||||
<p>{{interpretation.active_comments | length}}</p>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</dt>
|
||||
</div>
|
||||
</dl>
|
||||
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
67
app/templates/searchResultsTags.html
Normal file
67
app/templates/searchResultsTags.html
Normal file
@ -0,0 +1,67 @@
|
||||
<!-- prettier-ignore -->
|
||||
{% extends 'base.html' %}
|
||||
{% block content %}
|
||||
<div class="border-b border-gray-200 dark:border-gray-700 md:mr-64">
|
||||
<!-- prettier-ignore -->
|
||||
<h1 class="hidden md:inline font-extrabold text-lg dark:text-white ml-4 mt-5">Search results</h1>
|
||||
<!-- prettier-ignore -->
|
||||
<p class="hidden md:block text-sm ml-4 w-1/2 text-gray-500 text-center md:text-left dark:text-gray-400"> Search result for {{query}} </p>
|
||||
<!-- prettier-ignore -->
|
||||
<p class="hidden md:block text-sm ml-4 w-1/2 text-gray-500 text-center md:text-left dark:text-gray-400"> Showing {{count}} results </p>
|
||||
<!-- prettier-ignore -->
|
||||
<div class="border-b border-gray-200 dark:border-gray-700">
|
||||
<ul class="flex flex-wrap -mb-px text-sm font-medium text-center text-gray-500 dark:text-gray-400">
|
||||
<li class="mr-2">
|
||||
<a href="{{url_for('search.search_interpretations',q=query)}}" class="inline-flex p-4 border-b-2 border-transparent rounded-t-lg hover:text-gray-600 hover:border-gray-300 dark:hover:text-gray-300 group" >
|
||||
<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 mr-2 text-gray-400 group-hover:text-gray-500 dark:text-gray-500 dark:group-hover:text-gray-300" fill="currentColor" viewBox="0 0 24 24" stroke-width="1.5" > <path stroke-linecap="round" stroke-linejoin="round" d="M3.75 13.5l10.5-11.25L12 10.5h8.25L9.75 21.75 12 13.5H3.75z" /> </svg>
|
||||
Interpretations
|
||||
</a>
|
||||
</li>
|
||||
<li class="mr-2">
|
||||
<a href="{{url_for('search.search_books',q=query)}}" class="inline-flex p-4 border-b-2 border-transparent rounded-t-lg hover:text-gray-600 hover:border-gray-300 dark:hover:text-gray-300 group">
|
||||
<svg aria-hidden="true" class="w-5 h-5 mr-2 text-gray-400 group-hover:text-gray-500 dark:text-gray-500 dark:group-hover:text-gray-300" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M16.5 3.75V16.5L12 14.25 7.5 16.5V3.75m9 0H18A2.25 2.25 0 0120.25 6v12A2.25 2.25 0 0118 20.25H6A2.25 2.25 0 013.75 18V6A2.25 2.25 0 016 3.75h1.5m9 0h-9" /> </svg>
|
||||
Books
|
||||
</a>
|
||||
</li>
|
||||
<li class="mr-2">
|
||||
<a href="{{url_for('search.search_users'q=query)}}" class="inline-flex p-4 border-b-2 border-transparent rounded-t-lg hover:text-gray-600 hover:border-gray-300 dark:hover:text-gray-300 group">
|
||||
<svg aria-hidden="true" class="w-5 h-5 mr-2 text-gray-400 group-hover:text-gray-500 dark:text-gray-500 dark:group-hover:text-gray-300" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M17.982 18.725A7.488 7.488 0 0012 15.75a7.488 7.488 0 00-5.982 2.975m11.963 0a9 9 0 10-11.963 0m11.963 0A8.966 8.966 0 0112 21a8.966 8.966 0 01-5.982-2.275M15 9.75a3 3 0 11-6 0 3 3 0 016 0z" /> </svg>
|
||||
Users
|
||||
</a>
|
||||
</li>
|
||||
<li class="mr-2">
|
||||
<a class="inline-flex p-4 text-blue-600 border-b-2 border-blue-600 rounded-t-lg active dark:text-blue-500 dark:border-blue-500 group" aria-current="page">
|
||||
<svg aria-hidden="true" class="w-5 h-5 mr-2 text-blue-600 dark:text-blue-500" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M9.568 3H5.25A2.25 2.25 0 003 5.25v4.318c0 .597.237 1.17.659 1.591l9.581 9.581c.699.699 1.78.872 2.607.33a18.095 18.095 0 005.223-5.223c.542-.827.369-1.908-.33-2.607L11.16 3.66A2.25 2.25 0 009.568 3z" /> <path stroke-linecap="round" stroke-linejoin="round" d="M6 6h.008v.008H6V6z" /> </svg>
|
||||
Tags
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<!-- prettier-ignore -->
|
||||
<div class="md:mr-64 p-4 rounded-lg bg-gray-50 dark:bg-gray-800" id="users" role="tabpanel" aria-labelledby="users-tab">
|
||||
{% if count<1 %}
|
||||
<h1 class="hidden md:inline font-extrabold text-lg dark:text-white ml-4 mt-5">No {{query}} in any user name, try another search query.</h1>
|
||||
{% else %}
|
||||
<table class="w-full text-sm text-left text-gray-500 dark:text-gray-400">
|
||||
<thead class="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400"> <tr> <th scope="col" class="px-6 py-3">Username</th> <th scope="col" class="px-6 py-3">Action</th> </tr> </thead>
|
||||
<tbody>
|
||||
{% for user in users if not user.is_deleted %}
|
||||
<tr class="bg-white border-b dark:bg-gray-800 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600">
|
||||
<th scope="row" class="flex items-center px-6 py-4 text-gray-900 whitespace-nowrap dark:text-white">
|
||||
<img class="w-10 h-10 rounded-full" src="data:image/jpeg;base64,{{user.avatar_img}}" alt="User's avatar">
|
||||
<div class="pl-3">
|
||||
<div class="text-base font-semibold">{{user.username}}</div>
|
||||
<div class="font-normal text-gray-500">{{user.wallet_id}}</div>
|
||||
</div>
|
||||
</th>
|
||||
<td class="px-6 py-4">
|
||||
<a href="{{ url_for('user.profile',user_id=user.id) }}" class="font-medium text-blue-600 dark:text-blue-500 hover:underline">Go to {{user.username}}'s library</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
67
app/templates/searchResultsUsers.html
Normal file
67
app/templates/searchResultsUsers.html
Normal file
@ -0,0 +1,67 @@
|
||||
<!-- prettier-ignore -->
|
||||
{% extends 'base.html' %}
|
||||
{% block content %}
|
||||
<div class="border-b border-gray-200 dark:border-gray-700 md:mr-64">
|
||||
<!-- prettier-ignore -->
|
||||
<h1 class="hidden md:inline font-extrabold text-lg dark:text-white ml-4 mt-5">Search results</h1>
|
||||
<!-- prettier-ignore -->
|
||||
<p class="hidden md:block text-sm ml-4 w-1/2 text-gray-500 text-center md:text-left dark:text-gray-400"> Search result for {{query}} </p>
|
||||
<!-- prettier-ignore -->
|
||||
<p class="hidden md:block text-sm ml-4 w-1/2 text-gray-500 text-center md:text-left dark:text-gray-400"> Showing {{count}} results </p>
|
||||
<!-- prettier-ignore -->
|
||||
<div class="border-b border-gray-200 dark:border-gray-700">
|
||||
<ul class="flex flex-wrap -mb-px text-sm font-medium text-center text-gray-500 dark:text-gray-400">
|
||||
<li class="mr-2">
|
||||
<a href="{{url_for('search.search_interpretations',q=query)}}" class="inline-flex p-4 border-b-2 border-transparent rounded-t-lg hover:text-gray-600 hover:border-gray-300 dark:hover:text-gray-300 group" >
|
||||
<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 mr-2 text-gray-400 group-hover:text-gray-500 dark:text-gray-500 dark:group-hover:text-gray-300" fill="currentColor" viewBox="0 0 24 24" stroke-width="1.5" > <path stroke-linecap="round" stroke-linejoin="round" d="M3.75 13.5l10.5-11.25L12 10.5h8.25L9.75 21.75 12 13.5H3.75z" /> </svg>
|
||||
Interpretations
|
||||
</a>
|
||||
</li>
|
||||
<li class="mr-2">
|
||||
<a href="{{url_for('search.search_books',q=query)}}" class="inline-flex p-4 border-b-2 border-transparent rounded-t-lg hover:text-gray-600 hover:border-gray-300 dark:hover:text-gray-300 group">
|
||||
<svg aria-hidden="true" class="w-5 h-5 mr-2 text-gray-400 group-hover:text-gray-500 dark:text-gray-500 dark:group-hover:text-gray-300" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M16.5 3.75V16.5L12 14.25 7.5 16.5V3.75m9 0H18A2.25 2.25 0 0120.25 6v12A2.25 2.25 0 0118 20.25H6A2.25 2.25 0 013.75 18V6A2.25 2.25 0 016 3.75h1.5m9 0h-9" /> </svg>
|
||||
Books
|
||||
</a>
|
||||
</li>
|
||||
<li class="mr-2">
|
||||
<a class="inline-flex p-4 text-blue-600 border-b-2 border-blue-600 rounded-t-lg active dark:text-blue-500 dark:border-blue-500 group" aria-current="page" >
|
||||
<svg aria-hidden="true" class="w-5 h-5 mr-2 text-blue-600 dark:text-blue-500" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M17.982 18.725A7.488 7.488 0 0012 15.75a7.488 7.488 0 00-5.982 2.975m11.963 0a9 9 0 10-11.963 0m11.963 0A8.966 8.966 0 0112 21a8.966 8.966 0 01-5.982-2.275M15 9.75a3 3 0 11-6 0 3 3 0 016 0z" /> </svg>
|
||||
Users
|
||||
</a>
|
||||
</li>
|
||||
<li class="mr-2">
|
||||
<a href="{{url_for('search.search_tags',q=query)}}" class="inline-flex p-4 border-b-2 border-transparent rounded-t-lg hover:text-gray-600 hover:border-gray-300 dark:hover:text-gray-300 group">
|
||||
<svg aria-hidden="true" class="w-5 h-5 mr-2 text-gray-400 group-hover:text-gray-500 dark:text-gray-500 dark:group-hover:text-gray-300" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M9.568 3H5.25A2.25 2.25 0 003 5.25v4.318c0 .597.237 1.17.659 1.591l9.581 9.581c.699.699 1.78.872 2.607.33a18.095 18.095 0 005.223-5.223c.542-.827.369-1.908-.33-2.607L11.16 3.66A2.25 2.25 0 009.568 3z" /> <path stroke-linecap="round" stroke-linejoin="round" d="M6 6h.008v.008H6V6z" /> </svg>
|
||||
Tags
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<!-- prettier-ignore -->
|
||||
<div class="md:mr-64 p-4 rounded-lg bg-gray-50 dark:bg-gray-800" id="users" role="tabpanel" aria-labelledby="users-tab">
|
||||
{% if count<1 %}
|
||||
<h1 class="hidden md:inline font-extrabold text-lg dark:text-white ml-4 mt-5">No {{query}} in any user name, try another search query.</h1>
|
||||
{% else %}
|
||||
<table class="w-full text-sm text-left text-gray-500 dark:text-gray-400">
|
||||
<thead class="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400"> <tr> <th scope="col" class="px-6 py-3">Username</th> <th scope="col" class="px-6 py-3">Action</th> </tr> </thead>
|
||||
<tbody>
|
||||
{% for user in users if not user.is_deleted %}
|
||||
<tr class="bg-white border-b dark:bg-gray-800 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600">
|
||||
<th scope="row" class="flex items-center px-6 py-4 text-gray-900 whitespace-nowrap dark:text-white">
|
||||
<img class="w-10 h-10 rounded-full" src="data:image/jpeg;base64,{{user.avatar_img}}" alt="User's avatar">
|
||||
<div class="pl-3">
|
||||
<div class="text-base font-semibold">{{user.username}}</div>
|
||||
<div class="font-normal text-gray-500">{{user.wallet_id}}</div>
|
||||
</div>
|
||||
</th>
|
||||
<td class="px-6 py-4">
|
||||
<a href="{{ url_for('user.profile',user_id=user.id) }}" class="font-medium text-blue-600 dark:text-blue-500 hover:underline">Go to {{user.username}}'s library</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
@ -2,17 +2,13 @@
|
||||
<div class="hidden items-center justify-center py-1 bg-white dark:bg-gray-800 md:flex">
|
||||
<label for="table-search" class="sr-only" >Search</label>
|
||||
<div class="relative">
|
||||
<form action="{{ url_for('main.search') }}" method="post">
|
||||
{{ form_hidden_tag() }}
|
||||
<div class="absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none">
|
||||
<!-- prettier-ignore -->
|
||||
<svg class="w-5 h-5 text-gray-500 dark:text-gray-400" aria-hidden="true" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z" clip-rule="evenodd"></path></svg>
|
||||
</div>
|
||||
<!-- prettier-ignore -->
|
||||
<input id="mainSearchInput" required minlength="1" name="search_query" {% if search_query %}value={{ search_query }}{% endif %} type="text" class="block p-2 pl-10 text-sm text-gray-900 border border-gray-300 rounded-lg w-80 bg-gray-50 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
|
||||
|
||||
</div>
|
||||
<!-- prettier-ignore -->
|
||||
<button type="submit" id="table-search-user-button" class="md:flex px-3 py-2 text-xs text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 ml-2 font-medium rounded-lg text-center inline-flex items-center mr-2 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"><svg class="w-5 h-5 text-white-500" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6 ml-0 mr-1"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 15.75l-2.489-2.489m0 0a3.375 3.375 0 10-4.773-4.773 3.375 3.375 0 004.774 4.774zM21 12a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>Search</button>
|
||||
</form>
|
||||
<button type="button" id="global-search-button" class="md:flex px-3 py-2 text-xs text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 ml-2 font-medium rounded-lg text-center inline-flex items-center mr-2 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"><svg class="w-5 h-5 text-white-500" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6 ml-0 mr-1"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 15.75l-2.489-2.489m0 0a3.375 3.375 0 10-4.773-4.773 3.375 3.375 0 004.774 4.774zM21 12a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>Search</button>
|
||||
</div>
|
||||
|
@ -8,3 +8,4 @@ from .section import bp as section_blueprint
|
||||
from .vote import bp as vote_blueprint
|
||||
from .approve import bp as approve_blueprint
|
||||
from .star import bp as star_blueprint
|
||||
from .search import bp as search_blueprint
|
||||
|
@ -6,10 +6,7 @@ from flask import (
|
||||
)
|
||||
from flask_login import login_required, current_user
|
||||
|
||||
from app.controllers import (
|
||||
register_book_verify_route,
|
||||
create_breadcrumbs,
|
||||
)
|
||||
from app.controllers import register_book_verify_route, create_breadcrumbs, clean_html
|
||||
from app.controllers.delete_nested_book_entities import (
|
||||
delete_nested_interpretation_entities,
|
||||
)
|
||||
@ -122,6 +119,7 @@ def interpretation_create(
|
||||
if form.validate_on_submit():
|
||||
interpretation: m.Interpretation = m.Interpretation(
|
||||
text=form.text.data,
|
||||
plain_text=clean_html(form.text.data),
|
||||
section_id=section_id,
|
||||
user_id=current_user.id,
|
||||
)
|
||||
@ -179,6 +177,7 @@ def interpretation_edit(
|
||||
|
||||
if form.validate_on_submit():
|
||||
interpretation.text = form.text.data
|
||||
interpretation.plain_text = clean_html(form.text.data)
|
||||
|
||||
log(log.INFO, "Edit interpretation [%s]", interpretation.id)
|
||||
interpretation.save()
|
||||
|
@ -1,6 +1,4 @@
|
||||
from flask import redirect, url_for, Blueprint, render_template
|
||||
|
||||
from app import forms as f, models as m
|
||||
from flask import redirect, url_for, Blueprint
|
||||
|
||||
|
||||
main_blueprint = Blueprint("main", __name__)
|
||||
@ -9,32 +7,3 @@ main_blueprint = Blueprint("main", __name__)
|
||||
@main_blueprint.route("/")
|
||||
def index():
|
||||
return redirect(url_for("home.get_all"))
|
||||
|
||||
|
||||
@main_blueprint.route("/search", methods=["POST"])
|
||||
def search():
|
||||
form = f.SearchForm()
|
||||
if form.validate_on_submit():
|
||||
q = form.search_query.data
|
||||
users = m.User.query.order_by(m.User.id)
|
||||
if q:
|
||||
users = users.filter(m.User.username.like(f"%{q}%"))
|
||||
interpretations = m.Interpretation.query.order_by(m.Interpretation.id)
|
||||
if q:
|
||||
interpretations = interpretations.filter(
|
||||
m.Interpretation.text.like(f"%{q}%")
|
||||
)
|
||||
tags = m.Tag.query.order_by(m.Tag.id)
|
||||
if q:
|
||||
tags = tags.filter(m.Tag.name.like(f"%{q}%"))
|
||||
books = m.Book.query.order_by(m.Book.id)
|
||||
if q:
|
||||
books = books.filter(m.Book.label.like(f"%{q}%"))
|
||||
return render_template(
|
||||
"searchResult.html",
|
||||
query=q,
|
||||
users=users,
|
||||
interpretations=interpretations,
|
||||
tags=tags,
|
||||
books=books,
|
||||
)
|
||||
|
76
app/views/search.py
Normal file
76
app/views/search.py
Normal file
@ -0,0 +1,76 @@
|
||||
from flask import Blueprint, render_template, request
|
||||
from sqlalchemy import func
|
||||
|
||||
from app import models as m
|
||||
|
||||
|
||||
bp = Blueprint("search", __name__)
|
||||
|
||||
|
||||
@bp.route("/search_interpretations", methods=["GET"])
|
||||
def search_interpretations():
|
||||
q = request.args.get("q", type=str, default="").lower()
|
||||
interpretations = m.Interpretation.query.order_by(m.Interpretation.id)
|
||||
if q:
|
||||
interpretations = interpretations.filter(
|
||||
(func.lower(m.Interpretation.plain_text).like(f"%{q}%"))
|
||||
)
|
||||
count = interpretations.count()
|
||||
|
||||
books = m.Book.query.order_by(m.Book.id)
|
||||
if q:
|
||||
books = books.filter(m.Book.label.like(f"%{q}%"))
|
||||
return render_template(
|
||||
"searchResultsInterpretations.html",
|
||||
query=q,
|
||||
interpretations=interpretations,
|
||||
count=count,
|
||||
)
|
||||
|
||||
|
||||
@bp.route("/search_books", methods=["GET"])
|
||||
def search_books():
|
||||
q = request.args.get("q", type=str, default="")
|
||||
books = m.Book.query.order_by(m.Book.id)
|
||||
if q:
|
||||
books = books.filter((func.lower(m.Book.label).like(f"%{q}%")))
|
||||
count = books.count()
|
||||
|
||||
return render_template(
|
||||
"searchResultsBooks.html",
|
||||
query=q,
|
||||
books=books,
|
||||
count=count,
|
||||
)
|
||||
|
||||
|
||||
@bp.route("/search_users", methods=["GET"])
|
||||
def search_users():
|
||||
q = request.args.get("q", type=str, default="")
|
||||
users = m.User.query.order_by(m.User.id)
|
||||
if q:
|
||||
users = users.filter(func.lower(m.User.username).like(f"%{q}%"))
|
||||
count = users.count()
|
||||
|
||||
return render_template(
|
||||
"searchResultsUsers.html",
|
||||
query=q,
|
||||
users=users,
|
||||
count=count,
|
||||
)
|
||||
|
||||
|
||||
@bp.route("/search_tags", methods=["GET"])
|
||||
def search_tags():
|
||||
q = request.args.get("q", type=str, default="")
|
||||
tags = m.Tag.query.order_by(m.Tag.id)
|
||||
if q:
|
||||
tags = tags.filter(func.lower(m.Tag.name).like(f"%{q}%"))
|
||||
count = tags.count()
|
||||
|
||||
return render_template(
|
||||
"searchResultsUsers.html",
|
||||
query=q,
|
||||
tags=tags,
|
||||
count=count,
|
||||
)
|
32
migrations/versions/a9df3da8cd00_plain_text.py
Normal file
32
migrations/versions/a9df3da8cd00_plain_text.py
Normal file
@ -0,0 +1,32 @@
|
||||
"""plain_text
|
||||
|
||||
Revision ID: a9df3da8cd00
|
||||
Revises: 883298018384
|
||||
Create Date: 2023-05-23 10:42:06.239982
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = "a9df3da8cd00"
|
||||
down_revision = "883298018384"
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
with op.batch_alter_table("interpretations", schema=None) as batch_op:
|
||||
batch_op.add_column(sa.Column("plain_text", sa.Text()))
|
||||
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
with op.batch_alter_table("interpretations", schema=None) as batch_op:
|
||||
batch_op.drop_column("plain_text")
|
||||
|
||||
# ### end Alembic commands ###
|
@ -1,18 +1,34 @@
|
||||
export function slashSearch() {
|
||||
let firstClick: boolean = true;
|
||||
const searchBtn: HTMLButtonElement = document.querySelector(
|
||||
'#global-search-button',
|
||||
);
|
||||
const searchInput: HTMLInputElement =
|
||||
document.querySelector('#mainSearchInput');
|
||||
window.addEventListener('keypress', e => {
|
||||
const searchInput: HTMLInputElement =
|
||||
document.querySelector('#mainSearchInput');
|
||||
if (e.key === '/' && searchInput) {
|
||||
if (firstClick) {
|
||||
e.preventDefault();
|
||||
firstClick = false;
|
||||
}
|
||||
console.log(e.key);
|
||||
searchInput.focus();
|
||||
}
|
||||
searchInput.addEventListener('blur', () => {
|
||||
firstClick = true;
|
||||
});
|
||||
});
|
||||
if (searchBtn && searchInput) {
|
||||
searchBtn.addEventListener('click', async (e: any) => {
|
||||
e.preventDefault();
|
||||
const urlParams = new URLSearchParams({
|
||||
q: searchInput.value,
|
||||
});
|
||||
const res = await fetch('/search_interpretations?' + urlParams);
|
||||
if (res.status === 200) {
|
||||
window.location.replace(res.url);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user