Added label search and pages

This commit is contained in:
Michael Rodin 2023-11-07 12:58:40 +01:00
parent 78ed396c36
commit e6b69eb7b4
7 changed files with 130 additions and 39 deletions

View file

@ -1,6 +1,8 @@
# RAR-Index
It's some project for my school which is supposed to index _rar_-archives and make them searchable over a very ugly web frontend.
**!!Works only on python 3.10 and newer!!**
## Features
- Add and delete archives
- edit their labels (as their owner)

View file

@ -36,7 +36,7 @@ def convsize(s:int):
def homepage():
# try to get userdata, else logout state
logged_in,userdata=get_login_info(request.cookies.get('session-id'))
archives=db.get_n_archives()
archives,count=db.get_n_archives()
return render_template("home.html", title="Homepage",userdata=userdata,login=logged_in,archives=archives)
@app.route('/user')
@ -195,7 +195,8 @@ def labeleditpage(archid:int):
return render_template("labels.html", title="Edit Labels",userdata=userdata,login=logged_in,archive=archive,res_labels=label_dict,labels_names=labels_name_list)
@app.route('/search')
def searchpage():
@app.route('/search/<int:page>')
def searchpage(page:int=1):
# try to get userdata, else logout state
logged_in,userdata=get_login_info(request.cookies.get('session-id'))
@ -205,8 +206,12 @@ def searchpage():
except Exception as e:
sorttype="time"
try:
category=request.args['category']
label_dict=db.get_label_labeltypes(int(category))
category=int(request.args['category'])
catparentid=db.get_category_info(category)[2]
if catparentid:
label_dict=db.get_label_labeltypes(catparentid)
else:
label_dict=db.get_label_labeltypes(category)
except Exception as e:
category=0
label_dict={}
@ -215,7 +220,7 @@ def searchpage():
except Exception as e:
keywords=[]
try:
count=request.args['count']
count=int(request.args['count'])
except Exception as e:
count=20
labels=[]
@ -228,11 +233,16 @@ def searchpage():
continue
except Exception as e:
labels=[]
archives=db.get_n_archives(sorttype,category,keywords,count,labels)
archives,total_count=db.get_n_archives(sorttype,category,keywords,count,labels,page)
# if the requested page is larger than the maximum, return page 1
if page*count > total_count and (page-1)*count >= total_count:
page=1
archives,total_count=db.get_n_archives(sorttype,category,keywords,count,labels,page)
htmlcatlist=get_category_selection()
return render_template("search.html", title="Advanced Search",categories=htmlcatlist,userdata=userdata,login=logged_in,archives=archives,res_labels=label_dict,labels=labels)
return render_template("search.html", title="Advanced Search",page=page,count=count,total_count=total_count,categories=htmlcatlist,userdata=userdata,login=logged_in,archives=archives,res_labels=label_dict,labels=labels)
########## FUNCTIONS
@ -254,6 +264,7 @@ def get_login_info(sesskey:str):
userdata=()
return logged_in,userdata
## returns a cookie and redirects to the homepage
def setcookie(name:str,value:str,lifetime:int=10000):
resp = make_response(redirect('/'))
resp.set_cookie(name, value, max_age=lifetime)

View file

@ -184,6 +184,12 @@ class db:
self.cur.execute("SELECT * FROM Cats;")
return self.cur.fetchall()
## Gets and returns all info about one (1) category
## OUTPUT: tup=(ID:int,CATEGORY:str,PARENT:int,DESCRIPTION:str)
def get_category_info(self, catid:int):
self.cur.execute(f"SELECT * FROM Cats WHERE ID={catid}")
return self.cur.fetchone()
## get all labeltypes and their respective labels based on a category parent
## OUTPUT: res_dict:dict={…,LabType.NAME:[…,(ID:int,NAME:str),…],…}
def get_label_labeltypes(self, catparentid:int):
@ -245,24 +251,24 @@ class db:
return True, ""
## Returns n archives, sorted by a column
## OUTPUT: archives:array=[…,(ID:int,NAME:str,SIZE:str,IMPORTED[UNIX]:int),…]
def get_n_archives(self, sorttype:str="time",category:int=0, keywords:list=[], count:int=20,labels:list=[]): # TODO: CLEANN!!!!!
## OUTPUT: archives:array=[…,(ID:int,NAME:str,SIZE:str,IMPORTED[UNIX]:int),…], total_count:int
def get_n_archives(self, sorttype:str="time",category:int=0, keywords:list=[], count:int=20, labels:list=None, page:int=1): # TODO: CLEANN!!!!!
match sorttype:
case "size":
sorttype="SIZE DESC"
sorttype="Archs.SIZE DESC"
case "time":
sorttype="IMPORTED DESC"
sorttype="Archs.IMPORTED DESC"
case "za":
sorttype="NAME DESC"
sorttype="Archs.NAME DESC"
case _:
sorttype="NAME ASC"
sorttype="Archs.NAME ASC"
# create SQL query for keywords
keyword_string=""
for w in keywords:
keyword_string+=f"AND NAME LIKE '%{w}%' "
keyword_string+=f"AND Archs.NAME LIKE '%{w}%' "
if len(keywords) == 1:
keyword_string+=f"OR HASH = '{keywords[0]}' "
keyword_string+=f"OR Archs.HASH = '{keywords[0]}' "
# get all children of category (if exist) and put into query string
categories=self.get_categories()
@ -272,13 +278,20 @@ class db:
catlist.append(str(i[0]))
categories="(" + ",".join(catlist) + ")"
self.cur.execute(f"""SELECT Archs.ID,Archs.NAME,Archs.SIZE,Archs.IMPORTED FROM Archs
{"WHERE 1=1" if category==0 else "WHERE CATEGORY IN " + categories}
# select all archives by keywords, categories and labels
self.cur.execute(f"""SELECT DISTINCT Archs.ID,Archs.NAME,Archs.SIZE,Archs.IMPORTED FROM Archs
JOIN ArchLab ON Archs.ID=ArchLab.ArchID
{"WHERE 1=1" if category==0 else "WHERE Archs.CATEGORY IN " + categories}
{f"AND ArchLab.LabID IN ({','.join(labels)})" if labels else ""}
{keyword_string}
ORDER BY {sorttype} LIMIT {count if count else 20}""")
GROUP BY Archs.ID
{f"HAVING COUNT(Archs.ID)={len(labels)}" if labels else ""}
ORDER BY {sorttype}""")
archives=self.cur.fetchall()
res_archives=archives[page*count-count:page*count] # get archives for the selected page
total_count=len(archives)
return archives
return res_archives, total_count
if __name__ == "__main__":
#startup()

View file

@ -32,3 +32,43 @@ a.grid-item {
div.clickable:hover {
background: lightgrey;
}
div.pageselect {
display: grid;
grid-template-columns: 1fr max-content 1fr;
margin: 1em auto;
}
div.align-right {
display: inline-flex;
justify-content: end;
}
div.align-left {
display: inline-flex;
justify-content: left;
}
div.pageitem {
display: inline-block;
font-weight: 700;
text-align: center;
height: 2em;
width: 1.5em;
}
.pagebutton {
background: lightgrey;
font-weight: 600;
justify-self: auto;
border: none;
margin: 0 0.2em;
height: 2em;
width: 1.5em;
}
input.pagebutton:hover {
background: grey;
border: none;
}

View file

@ -6,6 +6,7 @@
{% block content %}
{% if archives|length > 0 %}
<h2>Newest archives</h2>
<div class="grid-container">
<div class="grid-header"><b>ARCHIVE</b></div>
<div class="grid-header"><b>SIZE</b></div>
@ -18,6 +19,6 @@
{% endfor %}
</div>
{% else %}
<p>No matching archives</p>
<p>Add some archives first!</p>
{% endif %}
{% endblock %}

View file

@ -18,7 +18,7 @@
<option value="size" {% if "size" == request.args.get('sort') %}selected="selected"{% endif %}>Archive Size</option>
</select>
<b>Category:</b>
<select name="category">
<select onchange="this.form.submit()" name="category">
<option value="0">None</option>
{% for i in categories %}
<option value="{{i[0]}}" {% if i[0] == request.args.get('category')|int %}selected="selected"{% endif %}>{{i[1]}}</option>
@ -26,7 +26,6 @@
</select>
<b>Count: </b><input type="number" name="count" step="1" placeholder="Number of items" {% if request.args.get('count') %}value="{{request.args.get('count')}}"{% else %} value="20"{% endif %}>
</div>
{# <!-- Can't get that to work
<div class="labels-container">
{% for ltype in res_labels %}
<div class="flex-item"><b>{{ltype}}</b>
@ -35,8 +34,7 @@
{% endfor %}
</div>
{% endfor %}
</div>-->
#}
</div>
</div>
{% if request.args.get('q') %}
<input type="text" name="q" value="{{request.args.get('q')}}" placeholder="Keywords">
@ -44,9 +42,9 @@
<input type="text" name="q" placeholder="Keywords">
{% endif %}
<input type="submit" value="Search!">
</form>
{% if archives|length > 0 %}
<div class="grid-container">
{% if archives|length > 0 %}
<div class="grid-container">
<div class="grid-header"><b>ARCHIVE</b></div>
<div class="grid-header"><b>SIZE</b></div>
<div class="grid-header"><b>IMPORTED</b></div>
@ -57,7 +55,33 @@
{% endfor %}
</div>
{% else %}
<p>No matching archives</p>
{% endif %}
{% else %}
<p>No matching archives</p>
{% endif %}
{% if total_count > page*count %}
<div class="pageselect">
<div class="align-right">
{% if page-3 > 1 %}
<div class="pageitem"></div>
{% endif %}
{% for pagenum in range(page-3,page) %}
{% if pagenum > 0 %}
<input class="pagebutton" type=submit formaction="/search/{{pagenum}}" value="{{pagenum}}">
{% endif %}
{% endfor %}
</div>
<div class="pageitem" id="currentpage">{{page}}</div>
<div class="align-left">
{% for pagenum in range(page+1,page+4) %}
{% if (pagenum-1)*count < total_count %}
<input class="pagebutton" type=submit formaction="/search/{{pagenum}}" value="{{pagenum}}">
{% endif %}
{% endfor %}
{% if (page+4)*count < total_count %}
<div class="pageitem"></div>
{% endif %}
</div>
</div>
{% endif %}
</form>
{% endblock %}

View file

@ -20,6 +20,6 @@
{% endfor %}
</div>
</div>
<img id="cover" src="/static/covers/{{archive[0]}}.webp" onerror="this.onerror=null; this.src='/static/covers/default.webp'" alt="Cover image">
<img id="cover" src="/static/covers/custom/{{archive[0]}}.webp" onerror="this.onerror=null; this.src='/static/covers/default.webp'" alt="Cover image">
</div>
{% endblock %}