diff --git a/frontend/__pycache__/groclist_fe.cpython-310.pyc b/frontend/__pycache__/groclist_fe.cpython-310.pyc new file mode 100644 index 0000000..851f3f3 Binary files /dev/null and b/frontend/__pycache__/groclist_fe.cpython-310.pyc differ diff --git a/frontend/__pycache__/hello.cpython-310.pyc b/frontend/__pycache__/hello.cpython-310.pyc new file mode 100644 index 0000000..e9fc610 Binary files /dev/null and b/frontend/__pycache__/hello.cpython-310.pyc differ diff --git a/frontend/app.py b/frontend/app.py new file mode 100644 index 0000000..5d7059c --- /dev/null +++ b/frontend/app.py @@ -0,0 +1,25 @@ +from flask import Flask, request, render_template, url_for, redirect + +app = Flask(__name__) + +@app.route("/") +def groclist_home(): + return render_template('index.html') + +@app.route("/welcome") +def groclist_welcome(): + return render_template("welcome.html") + +@app.route("/login", methods=['GET', 'POST']) +def groclist_login(): + error = None + if request.method == 'POST': + if request.form['username'] != 'admin' or request.form['password'] != 'admin': + error = 'Username of wachtwoord onbekend. Probeer opnieuw' + else: + return redirect(url_for('groclist_welcome')) + return render_template("login.html", error=error) + +# start server with run method +if __name__ == "__main__": + app.run(debug=True) diff --git a/frontend/static/style.css b/frontend/static/style.css new file mode 100644 index 0000000..b369a18 --- /dev/null +++ b/frontend/static/style.css @@ -0,0 +1,17 @@ +p { +font-family: Arial; +font-size: 16px; +color: black; +} + +h1 { +font-family: Arial; +font-size: 30px; +color: red; +} + +h2 { +font-family: Arial; +font-size: 24px; +color: orange; +} diff --git a/frontend/templates/base.html b/frontend/templates/base.html new file mode 100644 index 0000000..cbcc38b --- /dev/null +++ b/frontend/templates/base.html @@ -0,0 +1,17 @@ + + +
+ {% block head %} + ++ Welkom bij Groclist +
+{% endblock %} diff --git a/frontend/templates/login.html b/frontend/templates/login.html new file mode 100644 index 0000000..3ada399 --- /dev/null +++ b/frontend/templates/login.html @@ -0,0 +1,23 @@ + + +Error: {{ error }} + {% endif %} +
Click here to go home.
+Lorem ipsum..
+Test
Test
Lorem ipsum ...
+| One | +Two | +Three | +
Have a look at our other products
+``` + + +Decorators +---------- + +`Dominate` is great for creating reusable widgets for parts of your page. Consider this example: + +```python +def greeting(name): + with div() as d: + p('Hello, %s' % name) + return d + +print(greeting('Bob')) +``` +```html +Hello, Bob
+Hello Bob
+Hello Bob
+This is a paragraph.
+ + +``` + +Embedding HTML +-------------- + +If you need to embed a node of pre-formed HTML coming from a library such as markdown or the like, you can avoid escaped HTML by using the raw method from the dominate.util package: + +``` +from dominate.util import raw +... +td(raw('Example')) +``` + +Without the raw call, this code would render escaped HTML with lt, etc. + + +SVG +--- + +The `dominate.svg` module contains SVG tags similar to how `dominate.tags` contains HTML tags. SVG elements will automatically convert `_` to `-` for dashed elements. For example: + +```python +from dominate.svg import * +print(circle(stroke_width=5)) +``` + +```html +)
+ # otherwise, text will be escaped() and whitespace may be
+ # modified
+ is_inline = False
+
+
+ def __new__(_cls, *args, **kwargs):
+ '''
+ Check if bare tag is being used a a decorator
+ (called with a single function arg).
+ decorate the function and return
+ '''
+ if len(args) == 1 and isinstance(args[0], Callable) \
+ and not isinstance(args[0], dom_tag) and not kwargs:
+ wrapped = args[0]
+
+ @wraps(wrapped)
+ def f(*args, **kwargs):
+ with _cls() as _tag:
+ return wrapped(*args, **kwargs) or _tag
+ return f
+ return object.__new__(_cls)
+
+
+ def __init__(self, *args, **kwargs):
+ '''
+ Creates a new tag. Child tags should be passed as arguments and attributes
+ should be passed as keyword arguments.
+
+ There is a non-rendering attribute which controls how the tag renders:
+
+ * `__inline` - Boolean value. If True renders all children tags on the same
+ line.
+ '''
+
+ self.attributes = {}
+ self.children = []
+ self.parent = None
+ self.document = None
+
+ # Does not insert newlines on all children if True (recursive attribute)
+ self.is_inline = kwargs.pop('__inline', self.is_inline)
+ self.is_pretty = kwargs.pop('__pretty', self.is_pretty)
+
+ #Add child elements
+ if args:
+ self.add(*args)
+
+ for attr, value in kwargs.items():
+ self.set_attribute(*type(self).clean_pair(attr, value))
+
+ self._ctx = None
+ self._add_to_ctx()
+
+
+ # context manager
+ frame = namedtuple('frame', ['tag', 'items', 'used'])
+ # stack of frames
+ _with_contexts = defaultdict(list)
+
+ def _add_to_ctx(self):
+ stack = dom_tag._with_contexts.get(_get_thread_context())
+ if stack:
+ self._ctx = stack[-1]
+ stack[-1].items.append(self)
+
+
+ def __enter__(self):
+ stack = dom_tag._with_contexts[_get_thread_context()]
+ stack.append(dom_tag.frame(self, [], set()))
+ return self
+
+
+ def __exit__(self, type, value, traceback):
+ thread_id = _get_thread_context()
+ stack = dom_tag._with_contexts[thread_id]
+ frame = stack.pop()
+ for item in frame.items:
+ if item in frame.used: continue
+ self.add(item)
+ if not stack:
+ del dom_tag._with_contexts[thread_id]
+
+
+ def __call__(self, func):
+ '''
+ tag instance is being used as a decorator.
+ wrap func to make a copy of this tag
+ '''
+ # remove decorator from its context so it doesn't
+ # get added in where it was defined
+ if self._ctx:
+ self._ctx.used.add(self)
+
+ @wraps(func)
+ def f(*args, **kwargs):
+ tag = copy.deepcopy(self)
+ tag._add_to_ctx()
+ with tag:
+ return func(*args, **kwargs) or tag
+ return f
+
+
+ def set_attribute(self, key, value):
+ '''
+ Add or update the value of an attribute.
+ '''
+ if isinstance(key, int):
+ self.children[key] = value
+ elif isinstance(key, basestring):
+ self.attributes[key] = value
+ else:
+ raise TypeError('Only integer and string types are valid for assigning '
+ 'child tags and attributes, respectively.')
+ __setitem__ = set_attribute
+
+ def delete_attribute(self, key):
+ if isinstance(key, int):
+ del self.children[key:key+1]
+ else:
+ del self.attributes[key]
+ __delitem__ = delete_attribute
+
+ def setdocument(self, doc):
+ '''
+ Creates a reference to the parent document to allow for partial-tree
+ validation.
+ '''
+ # assume that a document is correct in the subtree
+ if self.document != doc:
+ self.document = doc
+ for i in self.children:
+ if not isinstance(i, dom_tag): return
+ i.setdocument(doc)
+
+
+ def add(self, *args):
+ '''
+ Add new child tags.
+ '''
+ for obj in args:
+ if isinstance(obj, numbers.Number):
+ # Convert to string so we fall into next if block
+ obj = str(obj)
+
+ if isinstance(obj, basestring):
+ obj = escape(obj)
+ self.children.append(obj)
+
+ elif isinstance(obj, dom_tag):
+ stack = dom_tag._with_contexts.get(_get_thread_context())
+ if stack:
+ stack[-1].used.add(obj)
+ self.children.append(obj)
+ obj.parent = self
+ obj.setdocument(self.document)
+
+ elif isinstance(obj, dict):
+ for attr, value in obj.items():
+ self.set_attribute(*dom_tag.clean_pair(attr, value))
+
+ elif hasattr(obj, '__iter__'):
+ for subobj in obj:
+ self.add(subobj)
+
+ else: # wtf is it?
+ raise ValueError('%r not a tag or string.' % obj)
+
+ if len(args) == 1:
+ return args[0]
+
+ return args
+
+
+ def add_raw_string(self, s):
+ self.children.append(s)
+
+
+ def remove(self, obj):
+ self.children.remove(obj)
+
+
+ def clear(self):
+ for i in self.children:
+ if isinstance(i, dom_tag) and i.parent is self:
+ i.parent = None
+ self.children = []
+
+
+ def get(self, tag=None, **kwargs):
+ '''
+ Recursively searches children for tags of a certain
+ type with matching attributes.
+ '''
+ # Stupid workaround since we can not use dom_tag in the method declaration
+ if tag is None: tag = dom_tag
+
+ attrs = [(dom_tag.clean_attribute(attr), value)
+ for attr, value in kwargs.items()]
+
+ results = []
+ for child in self.children:
+ if (isinstance(tag, basestring) and type(child).__name__ == tag) or \
+ (not isinstance(tag, basestring) and isinstance(child, tag)):
+
+ if all(child.attributes.get(attribute) == value
+ for attribute, value in attrs):
+ # If the child is of correct type and has all attributes and values
+ # in kwargs add as a result
+ results.append(child)
+ if isinstance(child, dom_tag):
+ # If the child is a dom_tag extend the search down through its children
+ results.extend(child.get(tag, **kwargs))
+ return results
+
+
+ def __getitem__(self, key):
+ '''
+ Returns the stored value of the specified attribute or child
+ (if it exists).
+ '''
+ if isinstance(key, int):
+ # Children are accessed using integers
+ try:
+ return object.__getattribute__(self, 'children')[key]
+ except KeyError:
+ raise IndexError('Child with index "%s" does not exist.' % key)
+ elif isinstance(key, basestring):
+ # Attributes are accessed using strings
+ try:
+ return object.__getattribute__(self, 'attributes')[key]
+ except KeyError:
+ raise AttributeError('Attribute "%s" does not exist.' % key)
+ else:
+ raise TypeError('Only integer and string types are valid for accessing '
+ 'child tags and attributes, respectively.')
+ __getattr__ = __getitem__
+
+
+ def __len__(self):
+ '''
+ Number of child elements.
+ '''
+ return len(self.children)
+
+
+ def __bool__(self):
+ '''
+ Hack for "if x" and __len__
+ '''
+ return True
+ __nonzero__ = __bool__
+
+
+ def __iter__(self):
+ '''
+ Iterates over child elements.
+ '''
+ return self.children.__iter__()
+
+
+ def __contains__(self, item):
+ '''
+ Checks recursively if item is in children tree.
+ Accepts both a string and a class.
+ '''
+ return bool(self.get(item))
+
+
+ def __iadd__(self, obj):
+ '''
+ Reflexive binary addition simply adds tag as a child.
+ '''
+ self.add(obj)
+ return self
+
+ # String and unicode representations are the same as render()
+ def __unicode__(self):
+ return self.render()
+ __str__ = __unicode__
+
+
+ def render(self, indent=' ', pretty=True, xhtml=False):
+ data = self._render([], 0, indent, pretty, xhtml)
+ return u''.join(data)
+
+
+ def _render(self, sb, indent_level, indent_str, pretty, xhtml):
+ pretty = pretty and self.is_pretty
+
+ name = getattr(self, 'tagname', type(self).__name__)
+
+ # Workaround for python keywords and standard classes/methods
+ # (del, object, input)
+ if name[-1] == '_':
+ name = name[:-1]
+
+ # open tag
+ sb.append('<')
+ sb.append(name)
+
+ for attribute, value in sorted(self.attributes.items()):
+ if value is not False: # False values must be omitted completely
+ sb.append(' %s="%s"' % (attribute, escape(unicode(value), True)))
+
+ sb.append(' />' if self.is_single and xhtml else '>')
+
+ if not self.is_single:
+ inline = self._render_children(sb, indent_level + 1, indent_str, pretty, xhtml)
+
+ if pretty and not inline:
+ sb.append('\n')
+ sb.append(indent_str * indent_level)
+
+ # close tag
+ sb.append('')
+ sb.append(name)
+ sb.append('>')
+
+ return sb
+
+ def _render_children(self, sb, indent_level, indent_str, pretty, xhtml):
+ inline = True
+ for child in self.children:
+ if isinstance(child, dom_tag):
+ if pretty and not child.is_inline:
+ inline = False
+ sb.append('\n')
+ sb.append(indent_str * indent_level)
+ child._render(sb, indent_level, indent_str, pretty, xhtml)
+ else:
+ sb.append(unicode(child))
+
+ return inline
+
+
+ def __repr__(self):
+ name = '%s.%s' % (self.__module__, type(self).__name__)
+
+ attributes_len = len(self.attributes)
+ attributes = '%s attribute' % attributes_len
+ if attributes_len != 1: attributes += 's'
+
+ children_len = len(self.children)
+ children = '%s child' % children_len
+ if children_len != 1: children += 'ren'
+
+ return '<%s at %x: %s, %s>' % (name, id(self), attributes, children)
+
+
+ @staticmethod
+ def clean_attribute(attribute):
+ '''
+ Normalize attribute names for shorthand and work arounds for limitations
+ in Python's syntax
+ '''
+
+ # Shorthand
+ attribute = {
+ 'cls': 'class',
+ 'className': 'class',
+ 'class_name': 'class',
+ 'fr': 'for',
+ 'html_for': 'for',
+ 'htmlFor': 'for',
+ }.get(attribute, attribute)
+
+ # Workaround for Python's reserved words
+ if attribute[0] == '_':
+ attribute = attribute[1:]
+
+ # Workaround for dash
+ special_prefix = any([attribute.startswith(x) for x in ('data_', 'aria_')])
+ if attribute in set(['http_equiv']) or special_prefix:
+ attribute = attribute.replace('_', '-').lower()
+
+ # Workaround for colon
+ if attribute.split('_')[0] in ('xlink', 'xml', 'xmlns'):
+ attribute = attribute.replace('_', ':', 1).lower()
+
+ return attribute
+
+
+ @classmethod
+ def clean_pair(cls, attribute, value):
+ '''
+ This will call `clean_attribute` on the attribute and also allows for the
+ creation of boolean attributes.
+
+ Ex. input(selected=True) is equivalent to input(selected="selected")
+ '''
+ attribute = cls.clean_attribute(attribute)
+
+ # Check for boolean attributes
+ # (i.e. selected=True becomes selected="selected")
+ if value is True:
+ value = attribute
+
+ # Ignore `if value is False`: this is filtered out in render()
+
+ return (attribute, value)
+
+
+_get_current_none = object()
+def get_current(default=_get_current_none):
+ '''
+ get the current tag being used as a with context or decorated function.
+ if no context is active, raises ValueError, or returns the default, if provided
+ '''
+ h = _get_thread_context()
+ ctx = dom_tag._with_contexts.get(h, None)
+ if ctx:
+ return ctx[-1].tag
+ if default is _get_current_none:
+ raise ValueError('no current context')
+ return default
+
+
+def attr(*args, **kwargs):
+ '''
+ Set attributes on the current active tag context
+ '''
+ c = get_current()
+ dicts = args + (kwargs,)
+ for d in dicts:
+ for attr, value in d.items():
+ c.set_attribute(*dom_tag.clean_pair(attr, value))
+
+
+# escape() is used in render
+from .util import escape
diff --git a/frontend/venv/lib/python3.10/site-packages/dominate/svg.py b/frontend/venv/lib/python3.10/site-packages/dominate/svg.py
new file mode 100644
index 0000000..787e371
--- /dev/null
+++ b/frontend/venv/lib/python3.10/site-packages/dominate/svg.py
@@ -0,0 +1,370 @@
+'''
+This module consists of classes specific to HTML5-SVG Elements. In general this module does not include
+- Elements that are not specific to SVG (eg. )
+- Elements that are deprecated
+'''
+from dominate.tags import html_tag
+from dominate.dom_tag import dom_tag
+import numbers
+
+
+__license__ = '''
+This file is part of Dominate.
+
+Dominate is free software: you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation, either version 3 of
+the License, or (at your option) any later version.
+
+Dominate is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General
+Public License along with Dominate. If not, see
+ .
+'''
+
+# Tag attributes
+_ATTR_GLOBAL = set([
+ 'accesskey', 'class', 'class', 'contenteditable', 'contextmenu', 'dir',
+ 'draggable', 'id', 'item', 'hidden', 'lang', 'itemprop', 'spellcheck',
+ 'style', 'subject', 'tabindex', 'title'
+])
+
+# https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/Events#Attributes
+_ATTR_EVENTS = set([
+ 'onbegin', 'onend', 'onrepeat',
+ 'onabort', 'onerror', 'onresize', 'onscroll', 'onunload',
+ 'oncopy', 'oncut', 'onpaste',
+ 'oncancel', 'oncanplay', 'oncanplaythrough', 'onchange', 'onclick', 'onclose', 'oncuechange', 'ondblclick',
+ 'ondrag', 'ondragend', 'ondragenter', 'ondragexit', 'ondragleave', 'ondragover', 'ondragstart', 'ondrop',
+ 'ondurationchange', 'onemptied', 'onended', 'onerror', 'onfocus', 'oninput', 'oninvalid', 'onkeydown', 'onkeypress',
+ 'onkeyup', 'onload', 'onloadeddata', 'onloadedmetadata','onloadstart', 'onmousedown', 'onmouseenter',
+ 'onmouseleave', 'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup', 'onmousewheel', 'onpause', 'onplay',
+ 'onplaying', 'onprogress', 'onratechange', 'onreset', 'onresize', 'onscroll', 'onseeked', 'onseeking', 'onselect',
+ 'onshow', 'onstalled', 'onsubmit', 'onsuspend', 'ontimeupdate', 'ontoggle', 'onvolumechange', 'onwaiting'
+])
+
+DASHED_ATTRIBUTES = set([
+ 'accent', 'alignment', 'arabic', 'baseline', 'cap', 'clip', 'color', 'dominant', 'enable', 'fill', 'flood',
+ 'font', 'glyph', 'horiz', 'image', 'letter', 'lighting', 'marker', 'overline', 'paint', 'panose', 'pointer',
+ 'rendering', 'shape', 'stop', 'strikethrough', 'stroke', 'text', 'underline', 'unicode', 'units', 'v', 'vector',
+ 'vert', 'word', 'writing', 'x'
+])
+
+
+# https://developer.mozilla.org/en-US/docs/Web/SVG/Element/svg
+class svg_tag(html_tag):
+ @staticmethod
+ def clean_attribute(attribute):
+ attribute = html_tag.clean_attribute(attribute)
+ words = attribute.split('_')
+ if words[0] in DASHED_ATTRIBUTES:
+ return attribute.replace('_', '-')
+ return attribute
+
+
+class svg(svg_tag):
+ pass
+
+
+class animate(svg_tag):
+ '''
+ The animate SVG element is used to animate an attribute or property of an element over time.
+ It's normally inserted inside the element or referenced by the href attribute of the target element.
+ '''
+ pass
+
+
+class animateMotion(svg_tag):
+ '''
+ The element causes a referenced element to move along a motion path.
+ '''
+ pass
+
+
+class animateTransform(svg_tag):
+ '''
+ The animateTransform element animates a transformation attribute on its target element, thereby allowing
+ animations to control translation, scaling, rotation, and/or skewing.
+ '''
+ is_single = True
+
+
+class circle(svg_tag):
+ '''
+ The SVG element is an SVG basic shape, used to draw circles based on a center point and a radius.
+ '''
+ pass
+
+
+class clipPath(svg_tag):
+ '''
+ The SVG element defines a clipping path, to be used used by the clip-path property.
+ '''
+ pass
+
+
+class defs(svg_tag):
+ '''
+ The element is used to store graphical objects that will be used at a later time. Objects created inside a
+ element are not rendered directly. To display them you have to reference them
+ (with a