* feat: added Subscription Banner and Manage Subscription button * feat[patch]: added a patch for adding `Manage Subscription` button in navbar_settings * chore: removed console ;) * refactor: make the `Manage Subscription` navbar item optional * keep it hidden by default, only show when the site configs are present * style: prettier, isort and stuff * chore: handling null responses, translation and refactored patch * fix: correct index reset * perf: reduce network/db calls If not sys manager then why make a request? * fix: removed network call and added subscription_expiry to boot process * chore: added enable_manage_susbcriptions as daily background job and refactored patch * chore: added hook to hooks.py * this looks clean enough, also don't have insert for child tables ;) Co-authored-by: Ankush Menat <ankush@frappe.io>version-14
@@ -1,7 +1,7 @@ | |||||
import sys | import sys | ||||
import requests | |||||
from urllib.parse import urlparse | from urllib.parse import urlparse | ||||
import requests | |||||
docs_repos = [ | docs_repos = [ | ||||
"frappe_docs", | "frappe_docs", | ||||
@@ -101,6 +101,7 @@ def get_bootinfo(): | |||||
bootinfo.app_logo_url = get_app_logo() | bootinfo.app_logo_url = get_app_logo() | ||||
bootinfo.link_title_doctypes = get_link_title_doctypes() | bootinfo.link_title_doctypes = get_link_title_doctypes() | ||||
bootinfo.translated_doctypes = get_translated_doctypes() | bootinfo.translated_doctypes = get_translated_doctypes() | ||||
bootinfo.subscription_expiry = add_subscription_expiry() | |||||
return bootinfo | return bootinfo | ||||
@@ -428,3 +429,10 @@ def load_currency_docs(bootinfo): | |||||
) | ) | ||||
bootinfo.docs += currency_docs | bootinfo.docs += currency_docs | ||||
def add_subscription_expiry(): | |||||
try: | |||||
return frappe.conf.subscription["expiry"] | |||||
except Exception: | |||||
return "" |
@@ -228,6 +228,7 @@ scheduler_events = { | |||||
"frappe.email.doctype.unhandled_email.unhandled_email.remove_old_unhandled_emails", | "frappe.email.doctype.unhandled_email.unhandled_email.remove_old_unhandled_emails", | ||||
"frappe.core.doctype.prepared_report.prepared_report.delete_expired_prepared_reports", | "frappe.core.doctype.prepared_report.prepared_report.delete_expired_prepared_reports", | ||||
"frappe.core.doctype.log_settings.log_settings.run_log_clean_up", | "frappe.core.doctype.log_settings.log_settings.run_log_clean_up", | ||||
"frappe.utils.subscription.enable_manage_subscription", | |||||
], | ], | ||||
"daily_long": [ | "daily_long": [ | ||||
"frappe.integrations.doctype.dropbox_settings.dropbox_settings.take_backups_daily", | "frappe.integrations.doctype.dropbox_settings.dropbox_settings.take_backups_daily", | ||||
@@ -213,3 +213,4 @@ frappe.patches.v14_0.set_suspend_email_queue_default | |||||
frappe.patches.v14_0.different_encryption_key | frappe.patches.v14_0.different_encryption_key | ||||
frappe.patches.v14_0.update_multistep_webforms | frappe.patches.v14_0.update_multistep_webforms | ||||
frappe.patches.v14_0.drop_unused_indexes | frappe.patches.v14_0.drop_unused_indexes | ||||
frappe.patches.v14_0.add_manage_subscriptions_in_navbar_settings |
@@ -0,0 +1,25 @@ | |||||
import frappe | |||||
def execute(): | |||||
navbar_settings = frappe.get_single("Navbar Settings") | |||||
if frappe.db.exists("Navbar Item", {"item_label": "Manage Subscriptions"}): | |||||
return | |||||
for idx, row in enumerate(navbar_settings.settings_dropdown[2:], start=4): | |||||
row.idx = idx | |||||
navbar_settings.append( | |||||
"settings_dropdown", | |||||
{ | |||||
"item_label": "Manage Subscriptions", | |||||
"item_type": "Action", | |||||
"action": "frappe.ui.toolbar.redirectToUrl()", | |||||
"is_standard": 1, | |||||
"hidden": 1, | |||||
"idx": 3, | |||||
}, | |||||
) | |||||
navbar_settings.save() |
@@ -1,6 +1,7 @@ | |||||
import frappe | |||||
import json | import json | ||||
import frappe | |||||
def execute(): | def execute(): | ||||
if frappe.db.exists("Social Login Key", "github"): | if frappe.db.exists("Social Login Key", "github"): | ||||
@@ -83,6 +83,7 @@ import "./frappe/ui/toolbar/search_utils.js"; | |||||
import "./frappe/ui/toolbar/about.js"; | import "./frappe/ui/toolbar/about.js"; | ||||
import "./frappe/ui/toolbar/navbar.html"; | import "./frappe/ui/toolbar/navbar.html"; | ||||
import "./frappe/ui/toolbar/toolbar.js"; | import "./frappe/ui/toolbar/toolbar.js"; | ||||
import "./frappe/ui/toolbar/subscription.js"; | |||||
// import "./frappe/ui/toolbar/notifications.js"; | // import "./frappe/ui/toolbar/notifications.js"; | ||||
import "./frappe/views/communication.js"; | import "./frappe/views/communication.js"; | ||||
import "./frappe/views/translation_manager.js"; | import "./frappe/views/translation_manager.js"; | ||||
@@ -0,0 +1,80 @@ | |||||
$(document).on("startup", async () => { | |||||
if (!frappe.boot.setup_complete || !frappe.user.has_role("System Manager")) { | |||||
return; | |||||
} | |||||
const expiry = frappe.boot.subscription_expiry; | |||||
if (expiry) { | |||||
let diff_days = | |||||
frappe.datetime.get_day_diff(cstr(expiry), frappe.datetime.get_today()) - 1; | |||||
let subscription_string = __( | |||||
`Your subscription will end in ${cstr(diff_days).bold()} ${ | |||||
diff_days > 1 ? "days" : "day" | |||||
}. After that your site will be suspended.` | |||||
); | |||||
let $bar = $(` | |||||
<div | |||||
class="position-fixed top-100 start-20 translate-middle shadow sm:rounded-lg py-2" | |||||
style="left: 10%; bottom:20px; width:80%; margin: auto; text-align: center; border-radius: 10px; background-color: rgb(240 249 255); z-index: 1" | |||||
> | |||||
<div | |||||
style="display: flex; align-items: center; justify-content: space-between; text-align: center;" | |||||
class="text-muted" | |||||
> | |||||
<p style="float: left; margin: auto; font-size: 17px">${subscription_string}</p> | |||||
<div style="display: flex; align-items: center; justify-content: space-between"> | |||||
<button | |||||
type="button" | |||||
class="button-renew px-4 py-2 border border-transparent text-white hover:bg-indigo-700 focus:outline-none focus:ring-offset-2 focus:ring-indigo-500" | |||||
style="background-color: #0089FF; border-radius: 5px; margin-right: 10px; height: fit-content;" | |||||
> | |||||
Subscribe | |||||
</button> | |||||
<a | |||||
type="button" | |||||
class="dismiss-upgrade text-muted" data-dismiss="modal" aria-hidden="true" style="font-size:30px; margin-bottom: 5px; margin-right: 10px" | |||||
> | |||||
\u00d7 | |||||
</a> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
`); | |||||
$("footer").append($bar); | |||||
$bar.find(".dismiss-upgrade").on("click", () => { | |||||
$bar.remove(); | |||||
}); | |||||
$bar.find(".button-renew").on("click", () => { | |||||
redirectToUrl(); | |||||
}); | |||||
} | |||||
}); | |||||
function redirectToUrl() { | |||||
frappe.call({ | |||||
method: "frappe.utils.subscription.remote_login", | |||||
callback: (url) => { | |||||
if (url.message !== false) { | |||||
window.open(url.message, "_blank"); | |||||
} else { | |||||
frappe.msgprint({ | |||||
title: __("Message"), | |||||
indicator: "orange", | |||||
message: __("No active subscriptions found."), | |||||
}); | |||||
} | |||||
}, | |||||
}); | |||||
} | |||||
$.extend(frappe.ui.toolbar, { | |||||
redirectToUrl() { | |||||
redirectToUrl(); | |||||
}, | |||||
}); |
@@ -258,6 +258,13 @@ def add_standard_navbar_items(): | |||||
"action": "frappe.ui.toolbar.route_to_user()", | "action": "frappe.ui.toolbar.route_to_user()", | ||||
"is_standard": 1, | "is_standard": 1, | ||||
}, | }, | ||||
{ | |||||
"item_label": "Manage Subscriptions", | |||||
"item_type": "Action", | |||||
"action": "frappe.ui.toolbar.redirectToUrl()", | |||||
"hidden": 1, | |||||
"is_standard": 1, | |||||
}, | |||||
{ | { | ||||
"item_label": "Session Defaults", | "item_label": "Session Defaults", | ||||
"item_type": "Action", | "item_type": "Action", | ||||
@@ -0,0 +1,35 @@ | |||||
import json | |||||
import requests | |||||
import frappe | |||||
@frappe.whitelist() | |||||
def remote_login(): | |||||
try: | |||||
login_url = frappe.conf.subscription["login_url"] | |||||
if frappe.conf.subscription["expiry"] and login_url: | |||||
resp = requests.post(login_url) | |||||
if resp.status_code != 200: | |||||
return | |||||
return json.loads(resp.text)["message"] | |||||
except Exception: | |||||
return False | |||||
return False | |||||
def enable_manage_subscription(): | |||||
if not frappe.db.exists("Navbar Item", {"item_label": "Manage Subscriptions"}): | |||||
return | |||||
navbar_item, hidden = frappe.db.get_value( | |||||
"Navbar Item", {"item_label": "Manage Subscriptions"}, ["name", "hidden"] | |||||
) | |||||
if navbar_item and hidden: | |||||
doc = frappe.get_cached_doc("Navbar Item", navbar_item) | |||||
doc.hidden = False | |||||
doc.save() |