From 243c2aa3fd1ce9594aac0d827926525ce8e89d43 Mon Sep 17 00:00:00 2001 From: Andrew Williams Date: Sat, 8 Jan 2022 15:25:19 +0000 Subject: [PATCH] Use client side rendering --- ohayodash/base.py | 116 +++++++++++++++++----------------- ohayodash/static/js/data.js | 16 +++++ ohayodash/static/js/script.js | 38 +++++++++++ ohayodash/static/js/search.js | 96 ++++++++++++++++++++++++++-- ohayodash/templates/index.j2 | 114 +++++++++++++++++++++------------ 5 files changed, 278 insertions(+), 102 deletions(-) create mode 100644 ohayodash/static/js/data.js create mode 100644 ohayodash/static/js/script.js diff --git a/ohayodash/base.py b/ohayodash/base.py index 9a68d14..a2fbad7 100644 --- a/ohayodash/base.py +++ b/ohayodash/base.py @@ -1,11 +1,8 @@ -import datetime -import logging import os -import zoneinfo import kubernetes import yaml -from flask import Blueprint, render_template, jsonify +from flask import Blueprint, jsonify, render_template ANNOTATION_BASE = 'ohayodash.github.io' @@ -14,11 +11,19 @@ base = Blueprint('base', __name__, template_folder='templates') def check_tags(tag, object): # Skip if we're limited to a tag, and the CM has tags but not that one. - tags = object.metadata.annotations.get('{0}/tags'.format(ANNOTATION_BASE), None) - if tag and tags: - if tag not in {x for x in tags.split(',') if x != ''}: - return False - return True + tags = object.metadata.annotations.get('{0}/tags'.format(ANNOTATION_BASE), '') + obj_tags = {x for x in tags.split(',') if x != ''} + + # If its not tagged, allow + if not obj_tags: + return True + + # If tag is on the object, allow + if tag in obj_tags: + return True + + # Else, disallow + return False def get_k8s_applications(tag: str = None) -> list: @@ -70,7 +75,7 @@ def get_bookmarks(tag: str = None) -> list: v1 = kubernetes.client.CoreV1Api() ret = v1.list_config_map_for_all_namespaces(watch=False) - bookmarks = {} + bookmarks = [] for cm in ret.items: # Skip if the CM has no annotations if cm.metadata.annotations is None: @@ -84,67 +89,64 @@ def get_bookmarks(tag: str = None) -> list: if not check_tags(tag, cm): continue + # Load bookmark data bookmark_data = yaml.safe_load(cm.data['bookmarks']) + + # Iterate each bookmark for bookmark in bookmark_data: if 'group' not in bookmark: group = 'default' else: group = bookmark['group'].lower() - if group not in bookmarks: - bookmarks[group] = [] - bookmarks[group].append(bookmark) + + # Find category dict and append or create + for cat in bookmarks: + if cat['category'] == group: + cat['links'].append(bookmark) + break + else: + bookmarks.append({'category': group, 'links': [bookmark]}) return bookmarks -def get_greeting() -> tuple: - """Generate the greeting string based on the defined timezone.""" - try: - tz = zoneinfo.ZoneInfo(os.environ.get('TZ', 'UTC')) - except zoneinfo.ZoneInfoNotFound: - logging.warning('Timezone {0} is invalid, using UTC'.format(os.environ.get('TZ', 'UTC'))) - tz = zoneinfo.ZoneInfo('UTC') - - current_time = datetime.datetime.now(tz) - - if 0 < current_time.hour < 12: - return 'おはようございます!', "Thats 'Good morning' in Japanese" - elif current_time.hour >= 19: - return 'こんばんは', "Thats 'Good evening' in Japanese" - return 'こんにちは', "Thats 'Good day' in Japanese" - - -# TODO: Replace with JS -@base.app_template_filter() -def format_datetime(value): - return value.strftime(os.environ.get('DATE_FORMAT', '%Y-%m-%d %H:%M')) # noqa: WPS323 - - @base.route('/') -def index(): - return render_template('index.j2', - greeting=get_greeting(), - now=datetime.datetime.utcnow(), - applications=get_k8s_applications(), - bookmarks=get_bookmarks(), - ) +@base.route('//') +def index(tag=None): + return render_template('index.j2') -@base.route('/') -def tag(tag): - return render_template('index.j2', - greeting=get_greeting(), - now=datetime.datetime.utcnow(), - applications=get_k8s_applications(tag), - bookmarks=get_bookmarks(tag), - ) +@base.route('/providers.json') +@base.route('//providers.json') +def providers(tag=None): + return jsonify({ + 'providers': [ + {'name': 'Allmusic', 'url': 'https://www.allmusic.com/search/all/', 'prefix': '/a'}, + {'name': 'Discogs', 'url': 'https://www.discogs.com/search/?q=', 'prefix': '/di'}, + {'name': 'Duck Duck Go', 'url': 'https://duckduckgo.com/?q=', 'prefix': '/d'}, + {'name': 'iMDB', 'url': 'https://www.imdb.com/find?q=', 'prefix': '/i'}, + {'name': 'TheMovieDB', 'url': 'https://www.themoviedb.org/search?query=', 'prefix': '/m'}, + {'name': 'Reddit', 'url': 'https://www.reddit.com/search?q=', 'prefix': '/r'}, + {'name': 'Qwant', 'url': 'https://www.qwant.com/?q=', 'prefix': '/q'}, + {'name': 'Soundcloud', 'url': 'https://soundcloud.com/search?q=', 'prefix': '/so'}, + {'name': 'Spotify', 'url': 'https://open.spotify.com/search/results/', 'prefix': '/s'}, + {'name': 'TheTVDB', 'url': 'https://www.thetvdb.com/search?query=', 'prefix': '/tv'}, + {'name': 'Trakt', 'url': 'https://trakt.tv/search?query=', 'prefix': '/t'} + ] + }) -@base.route('/api/applications') -def applications(): - return jsonify(get_k8s_applications()) +@base.route('/apps.json') +@base.route('//apps.json') +def applications(tag=None): + return jsonify({ + 'apps': get_k8s_applications(tag) + }) -@base.route('/api/bookmarks') -def bookmarks(): - return jsonify(get_bookmarks()) +@base.route('/links.json') +@base.route('//links.json') +def bookmarks(tag=None): + return jsonify({ + 'bookmarks': get_bookmarks(tag) + }) diff --git a/ohayodash/static/js/data.js b/ohayodash/static/js/data.js new file mode 100644 index 0000000..d91cb59 --- /dev/null +++ b/ohayodash/static/js/data.js @@ -0,0 +1,16 @@ +function fetchAndRender (name) { + fetch(name + '.json') + .then(response => response.json()) + .then(data => { + const mysource = document.getElementById(name + '-template').innerHTML; + const mytemplate = Handlebars.compile(mysource); + const myresult = mytemplate(data); + document.getElementById(name).innerHTML = myresult; + }); +} + +document.addEventListener('DOMContentLoaded', () => { + fetchAndRender('apps'); + fetchAndRender('links'); + fetchAndRender('providers'); +}); \ No newline at end of file diff --git a/ohayodash/static/js/script.js b/ohayodash/static/js/script.js new file mode 100644 index 0000000..616fd87 --- /dev/null +++ b/ohayodash/static/js/script.js @@ -0,0 +1,38 @@ +function date() { + let currentDate = new Date(); + let dateOptions = { + weekday: "long", + year: "numeric", + month: "long", + day: "numeric" + }; + let date = currentDate.toLocaleDateString("en-GB", dateOptions); + document.getElementById("header_date").innerHTML = date; +} + +function greet() { + let currentTime = new Date(); + let greet = Math.floor(currentTime.getHours() / 6); + let greeting = "こんにちは!"; + switch (greet) { + case 0: + greeting = "おやすみなさい!"; + break; + case 1: + greeting = "おはようございます!"; + break; + case 2: + greeting = "こんにちは!"; + break; + case 3: + greeting = "こんばんは!"; + break; + } + document.getElementById("header_greet").innerHTML = greeting; + document.title = greeting; +} + +function loadFunctions() { + date(); + greet(); +} diff --git a/ohayodash/static/js/search.js b/ohayodash/static/js/search.js index 1bdee3b..24c02c8 100755 --- a/ohayodash/static/js/search.js +++ b/ohayodash/static/js/search.js @@ -1,5 +1,6 @@ var sindex = 0; var cycle = false; +var sengine = "https://www.google.com/?q="; // Default search engine function start() { var query = getParameterByName('q'); @@ -20,7 +21,30 @@ function handleKeyPress(e) { if (key == 13) { // Search functions search(text); } - if (key == 32) { //Space to go to search + if (key == 9) { // Tab Completion Functions + e.preventDefault(); + e.stopPropagation(); + if (text[0] === ';') { + switch (option) { + case 't': + var streamers = ['admiralbahroo', 'moonmoon_ow', 'witwix']; + if (!subtext || cycle) { + cycle = true; + if (sindex > streamers.length - 1) sindex = 0; + document.getElementById("keywords").value = ';t ' + streamers[sindex++]; + return; + } + for (var streamer of streamers) { + if (subtext === streamer.substr(0, subtext.length)) { + document.getElementById("keywords").value = ';t ' + streamer; + return; + } + } + break; + } + } + } + if(key == 32){ //Space to go to search document.getElementById("keywords").focus(); } sindex = 0; @@ -28,13 +52,75 @@ function handleKeyPress(e) { } function search(text) { - if (validURL(text)) { + var option = text.substr(1, text.indexOf(' ') - 1) || text.substr(1); + var subtext = text.substr(2 + option.length); + if (text[0] === '/') { + if (text.indexOf(' ') > -1) { + switch (option) { + case "am": + window.location = "https://www.allmusic.com/search/all/" + subtext; + break; + case "d": + window.location = "https://duckduckgo.com/?q=" + subtext; + break; + case "di": + window.location = "https://www.discogs.com/search/?q=" + subtext; + break; + case "i": + window.location = "https://www.imdb.com/find?q=" + subtext; + break; + case "m": + window.location = "https://www.themoviedb.org/search?query=" + subtext; + break; + case "r": + window.location = "https://www.reddit.com/search?q=" + subtext; + break; + case "q": + window.location = "https://www.qwant.com/?q=" + subtext; + break; + case "so": + window.location = "https://soundcloud.com/search?q=" + subtext; + break; + case "s": + window.location = "https://open.spotify.com/search/results/" + subtext; + break; + case "t": + window.location = "https://trakt.tv/search?query=" + subtext; + break; + case "tv": + window.location = "https://www.thetvdb.com/search?query=" + subtext; + break; + case "y": + window.location = "https://www.youtube.com/results?search_query=" + subtext; + break; + case "g": + window.location = "https://www.google.com/?q=" + subtext; + break; + } + } else { + var option = text.substr(1); + switch (option) { + case "d": + window.location = "https://www.duckduckgo.com"; + break; + case "y": + window.location = "https://www.youtube.com"; + break; + case "r": + window.location = "https://reddit.com"; + break; + case "s": + window.location = "https://open.spotify.com"; + break; + } + } + } else if (validURL(text)) { if (containsProtocol(text)) window.location = text; else window.location = "https://" + text; } else { - window.location = "https://www.google.com/search?q=" + text; + window.location = sengine + text; } } @@ -54,7 +140,7 @@ function containsProtocol(str) { return !!pattern.test(str); } -String.prototype.replaceAll = function (search, replacement) { +String.prototype.replaceAll = function(search, replacement) { var target = this; return target.split(search).join(replacement); -}; +}; \ No newline at end of file diff --git a/ohayodash/templates/index.j2 b/ohayodash/templates/index.j2 index bcc87cc..7f0db30 100644 --- a/ohayodash/templates/index.j2 +++ b/ohayodash/templates/index.j2 @@ -2,17 +2,19 @@ - {{ title | default("おはよう!") }} + おはよう! + - - + + - + +
+ - {% if applications %}
+ {% raw %} + + {% endraw %}
- {% endif %} - {% if bookmarks %} - {% endif %}
- - + + + + + \ No newline at end of file