Skip to content

Commit

Permalink
Improve UI and design (#161)
Browse files Browse the repository at this point in the history
  • Loading branch information
Uzay-G committed Jan 1, 2021
1 parent 53b72fe commit 947947e
Show file tree
Hide file tree
Showing 27 changed files with 1,251 additions and 616 deletions.
8 changes: 8 additions & 0 deletions archivy/__init__.py
Expand Up @@ -57,4 +57,12 @@ def load_user(user_id):

app.jinja_options["extensions"].append("jinja2.ext.do")


@app.template_filter('pluralize')
def pluralize(number, singular='', plural='s'):
if number == 1:
return singular
else:
return plural

from archivy import routes # noqa:
4 changes: 0 additions & 4 deletions archivy/api.py
Expand Up @@ -41,14 +41,12 @@ def create_bookmark():
All parameters are sent through the JSON body.
- **url** (required)
- **desc**
- **tags**
- **path**
"""
json_data = request.get_json()
bookmark = DataObj(
url=json_data['url'],
desc=json_data.get('desc'),
tags=json_data.get('tags'),
path=json_data.get("path", ""),
type="bookmark",
Expand All @@ -72,15 +70,13 @@ def create_note():
All parameters are sent through the JSON body.
- **title** (required)
- **content** (required)
- **desc**
- **tags**
- **path**
"""
json_data = request.get_json()
note = DataObj(
title=json_data["title"],
content=json_data["content"],
desc=json_data.get("desc"),
tags=json_data.get("tags"),
path=json_data.get("path", ""),
type="note"
Expand Down
1 change: 0 additions & 1 deletion archivy/config.py
Expand Up @@ -48,7 +48,6 @@ def __init__(self):
},
"tags": {"type": "text", "analyzer": "rebuilt_standard"},
"body": {"type": "text", "analyzer": "rebuilt_standard"},
"desc": {"type": "text", "analyzer": "rebuilt_standard"}
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions archivy/data.py
Expand Up @@ -48,11 +48,11 @@ def get_items(collections=[], path="", structured=True, json_format=False):
- **json_format**: boolean value used internally to pre-process dataobjs
to send back a json response.
"""
datacont = Directory("root") if structured else []
home_dir = get_data_dir()
for filename in home_dir.rglob(path + "*"):
datacont = Directory(path or "root") if structured else []
root_dir = get_data_dir() / path
for filename in root_dir.rglob("*"):
if structured:
paths = filename.relative_to(home_dir)
paths = filename.relative_to(root_dir)
current_dir = datacont

# iterate through paths
Expand Down
18 changes: 13 additions & 5 deletions archivy/forms.py
@@ -1,28 +1,36 @@
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField, SelectField, PasswordField
from wtforms import StringField, SubmitField, SelectField, PasswordField, HiddenField
from wtforms.validators import DataRequired, URL


class NewBookmarkForm(FlaskForm):
url = StringField("url", validators=[DataRequired(), URL()])
path = SelectField("Topic")
desc = StringField("desc")
tags = StringField("tags")
path = SelectField("Folder")
submit = SubmitField("Save")


class NewNoteForm(FlaskForm):
title = StringField("title", validators=[DataRequired()])
path = SelectField("Topic")
desc = StringField("desc")
tags = StringField("tags")
path = SelectField("Folder")
submit = SubmitField("Save")


class NewFolderForm(FlaskForm):
parent_dir = HiddenField()
new_dir = StringField("New folder", validators=[DataRequired()])
submit = SubmitField("Create sub directory")


class DeleteDataForm(FlaskForm):
submit = SubmitField("Delete")


class DeleteFolderForm(FlaskForm):
dir_name = HiddenField(validators=[DataRequired()])


class UserForm(FlaskForm):
username = StringField("username")
password = PasswordField("password")
Expand Down
15 changes: 5 additions & 10 deletions archivy/models.py
Expand Up @@ -52,7 +52,6 @@ class DataObj:
[Optional attrs that if passed, will be set by the class]
- desc
- tags
- content
- path
Expand All @@ -69,15 +68,13 @@ class DataObj:
the db with their contents.
"""

__searchable__ = ["title", "content", "desc", "tags"]
__searchable__ = ["title", "content", "tags"]

id: Optional[int] = attrib(validator=optional(instance_of(int)),
default=None)
type: str = attrib(validator=instance_of(str))
title: str = attrib(validator=instance_of(str), default="")
content: str = attrib(validator=instance_of(str), default="")
desc: Optional[str] = attrib(validator=optional(instance_of(str)),
default=None)
tags: List[str] = attrib(validator=instance_of(list), default=[])
url: Optional[str] = attrib(validator=optional(instance_of(str)),
default=None)
Expand All @@ -97,22 +94,22 @@ def process_bookmark_url(self):
try:
url_request = requests.get(self.url)
except Exception:
flash(f"Could not retrieve {self.url}\n")
flash(f"Could not retrieve {self.url}\n", "error")
self.wipe()
return

try:
parsed_html = BeautifulSoup(url_request.text,
features="html.parser")
except Exception:
flash(f"Could not parse {self.url}\n")
flash(f"Could not parse {self.url}\n", "error")
self.wipe()
return

try:
self.content = self.extract_content(parsed_html)
except Exception:
flash(f"Could not extract content from {self.url}\n")
flash(f"Could not extract content from {self.url}\n", "error")
return

parsed_title = parsed_html.title
Expand All @@ -122,7 +119,6 @@ def process_bookmark_url(self):
def wipe(self):
"""Resets and invalidates dataobj"""
self.title = ""
self.desc = None
self.content = ""

def extract_content(self, beautsoup):
Expand Down Expand Up @@ -177,7 +173,6 @@ def insert(self):
hooks.before_dataobj_create(self)
data = {
"type": self.type,
"desc": self.desc,
"title": str(self.title),
"date": self.date.strftime("%x").replace("/", "-"),
"tags": self.tags,
Expand Down Expand Up @@ -220,7 +215,7 @@ def from_md(cls, md_content: str):
data = frontmatter.loads(md_content)
dataobj = {}
dataobj["content"] = data.content
for pair in ["tags", "desc", "id", "title", "path"]:
for pair in ["tags", "id", "title", "path"]:
try:
dataobj[pair] = data[pair]
except KeyError:
Expand Down
76 changes: 59 additions & 17 deletions archivy/routes.py
Expand Up @@ -2,7 +2,7 @@

import frontmatter
from flask import render_template, flash, redirect, request, url_for
from flask_login import login_user, login_required, current_user, logout_user
from flask_login import login_user, current_user, logout_user
from tinydb import Query
from werkzeug.security import check_password_hash, generate_password_hash

Expand Down Expand Up @@ -34,11 +34,17 @@ def check_perms():
@app.route("/")
@app.route("/index")
def index():
path = request.args.get("path", "")
files = data.get_items(path=path)
return render_template(
"home.html",
title="Home",
search_enabled=app.config["SEARCH_CONF"]["enabled"],
)
dir=files,
current_path=path,
new_folder_form=forms.NewFolderForm(),
delete_form=forms.DeleteFolderForm()
)


# TODO: refactor two following methods
Expand All @@ -51,15 +57,19 @@ def new_bookmark():
tags = form.tags.data.split(",") if form.tags.data != "" else []
bookmark = DataObj(
url=form.url.data,
desc=form.desc.data,
tags=tags,
path=path,
type="bookmark")
bookmark.process_bookmark_url()
bookmark_id = bookmark.insert()
if bookmark_id:
flash("Bookmark Saved!")
flash("Bookmark Saved!", "success")
return redirect(f"/dataobj/{bookmark_id}")
# for bookmarklet
form.url.data = request.args.get("url", "")
path = request.args.get("path", "not classified").strip('/')
# handle empty argument
form.path.data = path if path != "" else "not classified"
return render_template(
"dataobjs/new.html",
title="New Bookmark",
Expand All @@ -75,14 +85,16 @@ def new_note():
tags = form.tags.data.split(",") if form.tags.data != "" else []
note = DataObj(
title=form.title.data,
desc=form.desc.data,
tags=tags,
path=path,
type="note")
note_id = note.insert()
if note_id:
flash("Note Saved!")
flash("Note Saved!", "success")
return redirect(f"/dataobj/{note_id}")
path = request.args.get("path", "not classified").strip('/')
# handle empty argument
form.path.data = path if path != "" else "not classified"
return render_template(
"/dataobjs/new.html",
title="New Note",
Expand All @@ -94,7 +106,7 @@ def show_dataobj(dataobj_id):
dataobj = data.get_item(dataobj_id)

if not dataobj:
flash("Data could not be found!")
flash("Data could not be found!", "error")
return redirect("/")

if request.args.get("raw") == "1":
Expand All @@ -112,9 +124,9 @@ def delete_data(dataobj_id):
try:
data.delete_item(dataobj_id)
except BaseException:
flash("Data could not be found!")
flash("Data could not be found!", "error")
return redirect("/")
flash("Data deleted!")
flash("Data deleted!", "success")
return redirect("/")


Expand All @@ -128,26 +140,24 @@ def login():
if user and check_password_hash(user[0]["hashed_password"], form.password.data):
user = User.from_db(user[0])
login_user(user, remember=True)
flash("Login successful!")
flash("Login successful!", "success")

next_url = request.args.get("next")
return redirect(next_url or "/")

flash("Invalid credentials")
flash("Invalid credentials", "error")
return redirect("/login")
return render_template("users/form.html", form=form, title="Login")
return render_template("users/login.html", form=form, title="Login")


@app.route("/logout", methods=["DELETE"])
@login_required
def logout():
logout_user()
flash("Logged out successfully")
flash("Logged out successfully", "success")
return redirect("/")


@app.route("/user/edit", methods=["GET", "POST"])
@login_required
def edit_user():
form = forms.UserForm()
if form.validate_on_submit():
Expand All @@ -159,7 +169,39 @@ def edit_user():
},
doc_ids=[current_user.id]
)
flash("Information saved!")
flash("Information saved!", "success")
return redirect("/")
form.username.data = current_user.username
return render_template("users/form.html", title="Edit Profile", form=form)
return render_template("users/edit.html", form=form, title="Edit Profile")


@app.route("/folders/create", methods=["POST"])
def create_folder():
form = forms.NewFolderForm()
if form.validate_on_submit():
path = form.parent_dir.data + form.new_dir.data
print(path)
data.create_dir(path)
flash("Folder successfully created.", "success")
return redirect(f"/?path={path}")
flash("Could not create folder.", "error")
return redirect(request.referrer or "/")


@app.route("/folders/delete", methods=["POST"])
def delete_folder():
form = forms.DeleteFolderForm()
if form.validate_on_submit():
if data.delete_dir(form.dir_name.data):
flash("Folder successfully deleted.", "success")
return redirect("/")
else:
flash("Folder not found.", "error")
return redirect(request.referrer or "/", 404)
flash("Could not delete folder.", "error")
return redirect(request.referrer or "/")


@app.route("/bookmarklet")
def bookmarklet():
return render_template("bookmarklet.html", title="Bookmarklet")

0 comments on commit 947947e

Please sign in to comment.