aboutsummaryrefslogtreecommitdiffstats
path: root/pysite/views
diff options
context:
space:
mode:
Diffstat (limited to 'pysite/views')
-rw-r--r--pysite/views/staff/index.py21
-rw-r--r--pysite/views/staff/tables/__init__.py0
-rw-r--r--pysite/views/staff/tables/edit.py110
-rw-r--r--pysite/views/staff/tables/index.py13
-rw-r--r--pysite/views/staff/tables/table.py63
-rw-r--r--pysite/views/staff/tables/table_bare.py30
-rw-r--r--pysite/views/wiki/special/__init__.py1
7 files changed, 234 insertions, 4 deletions
diff --git a/pysite/views/staff/index.py b/pysite/views/staff/index.py
index 11447f87..fc05f1a7 100644
--- a/pysite/views/staff/index.py
+++ b/pysite/views/staff/index.py
@@ -3,14 +3,29 @@ from pprint import pformat
from flask import current_app
from pysite.base_route import RouteView
-from pysite.constants import ALL_STAFF_ROLES
+from pysite.constants import ALL_STAFF_ROLES, DEBUG_MODE, TABLE_MANAGER_ROLES
from pysite.decorators import require_roles
class StaffView(RouteView):
path = "/"
- name = "index"
+ name = "staff_index"
@require_roles(*ALL_STAFF_ROLES)
def get(self):
- return self.render("staff/staff.html", app_config=pformat(current_app.config, indent=4, width=120))
+ return self.render(
+ "staff/staff.html", manager=self.is_table_editor(),
+ app_config=pformat(current_app.config, indent=4, width=120)
+ )
+
+ def is_table_editor(self):
+ if DEBUG_MODE:
+ return True
+
+ data = self.user_data
+
+ for role in TABLE_MANAGER_ROLES:
+ if role in data.get("roles", []):
+ return True
+
+ return False
diff --git a/pysite/views/staff/tables/__init__.py b/pysite/views/staff/tables/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/pysite/views/staff/tables/__init__.py
diff --git a/pysite/views/staff/tables/edit.py b/pysite/views/staff/tables/edit.py
new file mode 100644
index 00000000..b70bc20e
--- /dev/null
+++ b/pysite/views/staff/tables/edit.py
@@ -0,0 +1,110 @@
+import json
+
+from flask import redirect, request, url_for
+from werkzeug.exceptions import BadRequest, NotFound
+
+from pysite.base_route import RouteView
+from pysite.constants import TABLE_MANAGER_ROLES
+from pysite.decorators import csrf, require_roles
+from pysite.mixins import DBMixin
+from pysite.tables import TABLES
+
+
+class TableEditView(RouteView, DBMixin):
+ path = "/tables/<table>/edit"
+ name = "tables.edit"
+
+ @require_roles(*TABLE_MANAGER_ROLES)
+ def get(self, table):
+ obj = TABLES.get(table)
+
+ if not obj:
+ # Unknown table
+ raise NotFound()
+
+ if obj.locked:
+ return redirect(url_for("staff.tables.table", table=table, page=1), code=303)
+
+ key = request.args.get("key")
+
+ old_primary = None
+
+ if key:
+ db_obj = self.db.get(table, key)
+ old_primary = key # Provide the current document's primary key, in case it's modified
+
+ document = json.dumps( # Editor uses JSON
+ db_obj,
+ indent=4
+ )
+ else:
+ document = json.dumps( # Generate default document from key schema
+ {k: "" for k in obj.keys},
+ indent=4
+ )
+
+ return self.render(
+ "staff/tables/edit.html", table=table, primary_key=obj.primary_key,
+ document=document, old_primary=old_primary
+ )
+
+ @require_roles(*TABLE_MANAGER_ROLES)
+ @csrf
+ def post(self, table):
+ obj = TABLES.get(TABLES)
+
+ if not obj:
+ # Unknown table
+ raise NotFound()
+
+ if obj.locked:
+ raise BadRequest()
+
+ data = request.form.get("json")
+ old_primary = request.form.get("old_primary")
+
+ if not data:
+ # No data given (for some reason)
+ document = json.dumps(
+ {k: "" for k in obj.keys},
+ indent=4
+ )
+
+ return self.render(
+ "staff/tables/edit.html", table=table, primary_key=obj.primary_key, document=document,
+ message="Please provide some data to save", old_primary=old_primary
+ )
+
+ try:
+ data = json.loads(data)
+ except json.JSONDecodeError as e:
+ # Invalid JSON
+ return self.render(
+ "staff/tables/edit.html", table=table, primary_key=obj.primary_key, document=data,
+ message=f"Invalid JSON, please try again: {e}", old_primary=old_primary
+ )
+
+ if not data[obj.primary_key]:
+ # No primary key value provided
+ return self.render(
+ "staff/tables/edit.html", table=table, primary_key=obj.primary_key, document=data,
+ message=f"Please provide a value for the primary key: {obj.primary_key}", old_primary=old_primary
+ )
+
+ if old_primary is None:
+ self.db.insert( # This is a new object, so just insert it
+ table, data
+ )
+ elif old_primary == data[obj.primary_key]:
+ self.db.insert( # This is an update without a primary key change, replace the whole document
+ table, data, conflict="replace"
+ )
+ else:
+ self.db.delete( # This is a primary key change, so we need to remove the old object
+ table, old_primary
+ )
+ self.db.insert(
+ table, data,
+ )
+
+ return redirect(url_for("staff.tables.table", table=table, page=1), code=303)
diff --git a/pysite/views/staff/tables/index.py b/pysite/views/staff/tables/index.py
new file mode 100644
index 00000000..0d84aeb4
--- /dev/null
+++ b/pysite/views/staff/tables/index.py
@@ -0,0 +1,13 @@
+from pysite.base_route import RouteView
+from pysite.constants import TABLE_MANAGER_ROLES
+from pysite.decorators import require_roles
+from pysite.tables import TABLES
+
+
+class TablesView(RouteView):
+ path = "/tables"
+ name = "tables.index"
+
+ @require_roles(*TABLE_MANAGER_ROLES)
+ def get(self):
+ return self.render("staff/tables/index.html", tables=TABLES)
diff --git a/pysite/views/staff/tables/table.py b/pysite/views/staff/tables/table.py
new file mode 100644
index 00000000..f47d7793
--- /dev/null
+++ b/pysite/views/staff/tables/table.py
@@ -0,0 +1,63 @@
+from math import ceil
+
+from flask import request
+from werkzeug.exceptions import BadRequest, NotFound
+
+from pysite.base_route import RouteView
+from pysite.constants import TABLE_MANAGER_ROLES
+from pysite.decorators import require_roles
+from pysite.mixins import DBMixin
+from pysite.tables import TABLES
+
+
+class TableView(RouteView, DBMixin):
+ path = "/tables/<table>/<page>"
+ name = "tables.table"
+
+ @require_roles(*TABLE_MANAGER_ROLES)
+ def get(self, table, page):
+ search = request.args.get("search")
+ search_key = request.args.get("search-key")
+
+ pages = page
+ obj = TABLES.get(table)
+
+ if not obj:
+ return NotFound()
+
+ if search:
+ new_search = f"(?i){search}" # Case-insensitive search
+ search_key = search_key or obj.primary_key
+
+ query = self.db.query(table).filter(lambda d: d[search_key].match(new_search))
+ else:
+ query = self.db.query(table)
+
+ if page != "all":
+ try:
+ page = int(page)
+ except ValueError:
+ # Not an integer
+ return BadRequest()
+
+ count = self.db.run(query.count(), coerce=int)
+ pages = max(ceil(count / 10), 1) # Pages if we have 10 documents per page, always at least one
+
+ if page < 1 or page > pages:
+ # If the page is too small or too big, well, that's an error
+ return BadRequest()
+
+ documents = self.db.run( # Get only the documents for this page
+ query.skip((page - 1) * 10).limit(10),
+ coerce=list
+ )
+ else:
+ documents = self.db.run(query, coerce=list)
+
+ documents = [dict(sorted(d.items())) for d in documents]
+
+ return self.render(
+ "staff/tables/table.html",
+ table=table, documents=documents, table_obj=obj,
+ page=page, pages=pages, search=search, search_key=search_key
+ )
diff --git a/pysite/views/staff/tables/table_bare.py b/pysite/views/staff/tables/table_bare.py
new file mode 100644
index 00000000..abd6cb19
--- /dev/null
+++ b/pysite/views/staff/tables/table_bare.py
@@ -0,0 +1,30 @@
+from flask import redirect, request, url_for
+from werkzeug.exceptions import NotFound
+
+from pysite.base_route import RouteView
+from pysite.constants import TABLE_MANAGER_ROLES
+from pysite.decorators import require_roles
+from pysite.mixins import DBMixin
+from pysite.tables import TABLES
+
+
+class TableView(RouteView, DBMixin):
+ path = "/tables/<table>"
+ name = "tables.table_bare"
+
+ @require_roles(*TABLE_MANAGER_ROLES)
+ def get(self, table):
+ if table not in TABLES:
+ raise NotFound()
+
+ search = request.args.get("search")
+
+ args = {
+ "table": table,
+ "page": 1
+ }
+
+ if search is not None:
+ args["search"] = search
+
+ return redirect(url_for("staff.tables.table", **args))
diff --git a/pysite/views/wiki/special/__init__.py b/pysite/views/wiki/special/__init__.py
index 9bad5790..e69de29b 100644
--- a/pysite/views/wiki/special/__init__.py
+++ b/pysite/views/wiki/special/__init__.py
@@ -1 +0,0 @@
-# coding=utf-8