From ef0c3e4a24eca3a55f526db5a65a227d4d2e9ae1 Mon Sep 17 00:00:00 2001 From: Anand Chitipothu Date: Tue, 8 Jun 2021 10:36:12 +0530 Subject: [PATCH] feat: pluggable profile tabs Added ProfileTab class to represent a profile tab and made the profile page render the tabs specified in the hook `profile_tabs`. This allows plugging in new tabs in the profile page without makeing any changes to the community module. --- community/community/profile_tab.py | 38 +++++++++++++++++++++++++++++ community/www/profiles/profile.html | 33 ++++++++++++------------- community/www/profiles/profile.py | 15 ++++++++++-- 3 files changed, 66 insertions(+), 20 deletions(-) create mode 100644 community/community/profile_tab.py diff --git a/community/community/profile_tab.py b/community/community/profile_tab.py new file mode 100644 index 00000000..62e54dcb --- /dev/null +++ b/community/community/profile_tab.py @@ -0,0 +1,38 @@ +""" +The profile_tab module provides a pluggable way to add tabs to user +profiles. + +This is achieved by specifying the profile_tabs in the hooks. + + profile_tabs = [ + 'myapp.myapp.profile_tabs.SketchesTab' + ] + +When a profile page is rendered, these classes specified in the +profile_hooks are instanciated with the user as argument and used to +render the tabs. +""" + +class ProfileTab: + """Base class for profile tabs. + + Every subclass of ProfileTab must implement two methods: + - get_title() + - render() + """ + def __init__(self, user): + self.user = user + + def get_title(self): + """Returns the title of the tab. + + Every subclass must implement this. + """ + raise NotImplementedError() + + def render(self): + """Renders the contents of the tab as HTML. + + Every subclass must implement this. + """ + raise NotImplementedError() diff --git a/community/www/profiles/profile.html b/community/www/profiles/profile.html index d7f3daae..68e9a58c 100644 --- a/community/www/profiles/profile.html +++ b/community/www/profiles/profile.html @@ -72,29 +72,26 @@
-
-
-
- {% if sketches %} - {% for sketch in sketches %} -
- {{ widgets.SketchTeaser(sketch=sketch) }} -
- {% endfor %} - {% endif %} + {% for tab in profile_tabs %} + {% set slug = title.lower().replace(" ", "-") %} +
+
+ {{ tab.render() }}
- {% if not sketches %} -

{{member.full_name}} has not created any skecth yet.

- {% endif %}
-
+ {% endfor %}
diff --git a/community/www/profiles/profile.py b/community/www/profiles/profile.py index 5f0bf355..b6856cc0 100644 --- a/community/www/profiles/profile.py +++ b/community/www/profiles/profile.py @@ -3,9 +3,20 @@ from community.lms.models import Sketch def get_context(context): context.no_cache = 1 + try: context.member = frappe.get_doc("User", {"username": frappe.form_dict["username"]}) except: context.template = "www/404.html" - else: - context.sketches = Sketch.get_recent_sketches(owner=context.member.email) + return + + context.profile_tabs = get_profile_tabs(context.member) + +def get_profile_tabs(user): + """Returns the enabled ProfileTab objects. + + Each ProfileTab is rendered as a tab on the profile page and the + they are specified as profile_tabs hook. + """ + tabs = frappe.get_hooks("profile_tabs") or [] + return [frappe.get_attr(tab)(user) for tab in tabs]