├── .gitignore ├── MANIFEST.in ├── README.md ├── frappe_system_monitor ├── __init__.py ├── authentication.py ├── config │ ├── __init__.py │ ├── desktop.py │ └── docs.py ├── frappe_system_monitor │ ├── __init__.py │ └── page │ │ ├── __init__.py │ │ └── system_monitor │ │ ├── __init__.py │ │ ├── desctable.html │ │ ├── system_monitor.js │ │ ├── system_monitor.json │ │ └── system_monitor.py ├── hooks.py ├── modules.txt ├── patches.txt ├── public │ ├── build.json │ └── js │ │ ├── loader.js │ │ └── zingchart.min.js └── templates │ ├── __init__.py │ └── pages │ ├── __init__.py │ └── system_monitor.html ├── license.txt ├── requirements.txt └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.pyc 3 | *.egg-info 4 | *.swp 5 | tags 6 | frappe_system_monitor/docs/current -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include MANIFEST.in 2 | include requirements.txt 3 | include *.json 4 | include *.md 5 | include *.py 6 | include *.txt 7 | recursive-include frappe_system_monitor *.css 8 | recursive-include frappe_system_monitor *.csv 9 | recursive-include frappe_system_monitor *.html 10 | recursive-include frappe_system_monitor *.ico 11 | recursive-include frappe_system_monitor *.js 12 | recursive-include frappe_system_monitor *.json 13 | recursive-include frappe_system_monitor *.md 14 | recursive-include frappe_system_monitor *.png 15 | recursive-include frappe_system_monitor *.py 16 | recursive-include frappe_system_monitor *.svg 17 | recursive-include frappe_system_monitor *.txt 18 | recursive-exclude frappe_system_monitor *.pyc -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Frappe System Monitor 2 | 3 | System monitor for frappe and ERPNExt 4 | 5 | #### License 6 | 7 | MIT 8 | 9 | ## USAGE 10 | - bench get-app https://github.com/mymi14s/frappe_system_monitor 11 | - bench --site sitename install-app frappe_system_monitor 12 | - bench restart 13 | - login 14 | - open yoururl.com/app/system-monitor 15 | 16 | ![image](https://user-images.githubusercontent.com/10146518/164576659-861f767e-5891-4d0b-8cf6-4ddf981ef310.png) 17 | 18 | -------------------------------------------------------------------------------- /frappe_system_monitor/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | __version__ = '0.0.1' 3 | 4 | -------------------------------------------------------------------------------- /frappe_system_monitor/authentication.py: -------------------------------------------------------------------------------- 1 | import frappe 2 | from frappe.core.doctype.user.user import generate_keys 3 | 4 | 5 | @frappe.whitelist(allow_guest=True) 6 | def login(**kwargs): 7 | try: 8 | usr, pwd, cmd = frappe.form_dict.values() 9 | print(usr, pwd, cmd) 10 | auth = frappe.auth.LoginManager() 11 | auth.authenticate(user=usr, pwd=pwd) 12 | auth.post_login() 13 | msg={ 14 | 'status_code':200, 15 | 'text':frappe.local.response.message, 16 | 'user': frappe.session.user 17 | } 18 | user = frappe.get_doc('User', frappe.session.user) 19 | if(user.api_key and user.api_secret): 20 | msg['token'] = f"{user.api_key}:{user.get_password('api_secret')}" 21 | else: 22 | generate_keys(user.name) 23 | user.reload() 24 | msg['token'] = f"{user.api_key}:{user.get_password('api_secret')}" 25 | return msg 26 | except frappe.exceptions.AuthenticationError: 27 | return {'status_code':401, 'text':frappe.local.response.message} 28 | except Exception as e: 29 | return {'status_code':500, 'text':str(e)} 30 | -------------------------------------------------------------------------------- /frappe_system_monitor/config/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mymi14s/frappe_system_monitor/4aabbe32663464e6db24ab9e597c5f2bee576eed/frappe_system_monitor/config/__init__.py -------------------------------------------------------------------------------- /frappe_system_monitor/config/desktop.py: -------------------------------------------------------------------------------- 1 | from frappe import _ 2 | 3 | def get_data(): 4 | return [ 5 | { 6 | "module_name": "Frappe System Monitor", 7 | "color": "grey", 8 | "icon": "octicon octicon-file-directory", 9 | "type": "module", 10 | "label": _("Frappe System Monitor") 11 | } 12 | ] 13 | -------------------------------------------------------------------------------- /frappe_system_monitor/config/docs.py: -------------------------------------------------------------------------------- 1 | """ 2 | Configuration for docs 3 | """ 4 | 5 | # source_link = "https://github.com/[org_name]/frappe_system_monitor" 6 | # docs_base_url = "https://[org_name].github.io/frappe_system_monitor" 7 | # headline = "App that does everything" 8 | # sub_heading = "Yes, you got that right the first time, everything" 9 | 10 | def get_context(context): 11 | context.brand_html = "Frappe System Monitor" 12 | -------------------------------------------------------------------------------- /frappe_system_monitor/frappe_system_monitor/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mymi14s/frappe_system_monitor/4aabbe32663464e6db24ab9e597c5f2bee576eed/frappe_system_monitor/frappe_system_monitor/__init__.py -------------------------------------------------------------------------------- /frappe_system_monitor/frappe_system_monitor/page/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mymi14s/frappe_system_monitor/4aabbe32663464e6db24ab9e597c5f2bee576eed/frappe_system_monitor/frappe_system_monitor/page/__init__.py -------------------------------------------------------------------------------- /frappe_system_monitor/frappe_system_monitor/page/system_monitor/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mymi14s/frappe_system_monitor/4aabbe32663464e6db24ab9e597c5f2bee576eed/frappe_system_monitor/frappe_system_monitor/page/system_monitor/__init__.py -------------------------------------------------------------------------------- /frappe_system_monitor/frappe_system_monitor/page/system_monitor/desctable.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
OS{{name}}
Release{{release}}
Running Since{{running_since}}
19 | -------------------------------------------------------------------------------- /frappe_system_monitor/frappe_system_monitor/page/system_monitor/system_monitor.js: -------------------------------------------------------------------------------- 1 | frappe.pages['system-monitor'].on_page_load = function(wrapper) { 2 | new MyPage(wrapper); 3 | } 4 | 5 | // PAGE CONTENT 6 | MyPage = Class.extend({ 7 | init: function(wrapper){ 8 | this.page = frappe.ui.make_app_page({ 9 | parent: wrapper, 10 | title: 'System Monitor', 11 | single_column: true 12 | }); 13 | // make page 14 | frappe.require('/assets/frappe_system_monitor/js/loader.js', ()=>{ 15 | this.make(); 16 | }) 17 | }, 18 | 19 | // make page 20 | make: function(){ 21 | // grab the class 22 | let me = $(this); 23 | // push dom elemt to page 24 | 25 | // execute methods 26 | $(frappe.render_template(` 27 |
28 |
29 |
30 |
31 |
32 |
33 |
`, this)).appendTo(this.page.main); 34 | chart_data(); 35 | 36 | }// end of class 37 | }) 38 | 39 | 40 | let chart_data = () => { 41 | setTimeout(()=>{ 42 | get_chart_data(); 43 | chart_data(); 44 | }, 3000) 45 | } 46 | 47 | 48 | let get_chart_data = () => { 49 | frappe.call({ 50 | method: "frappe_system_monitor.frappe_system_monitor.page.system_monitor\ 51 | .system_monitor.execute", //dotted path to server method 52 | callback: function(r) { 53 | // code snippet 54 | data = r.message 55 | console.log(r); 56 | document.querySelector('#desc_table').innerHTML = data.desctable; 57 | render_guage(data); 58 | render_frequency(data.cpu); 59 | } 60 | }) 61 | } 62 | 63 | let render_guage = (r) => { 64 | google.charts.load('current', {'packages':['gauge']}); 65 | google.charts.setOnLoadCallback(drawChart); 66 | 67 | function drawChart() { 68 | 69 | var data = google.visualization.arrayToDataTable([ 70 | ['Label', 'Value'], 71 | ['RAM', r.memory.percent], 72 | ['CPU', r.cpu.percent], 73 | ['Disk', r.disk.percent] 74 | ]); 75 | 76 | var options = { 77 | width: '100%', height: 200, 78 | redFrom: 90, redTo: 100, 79 | yellowFrom:75, yellowTo: 90, 80 | minorTicks: 5 81 | }; 82 | 83 | var chart = new google.visualization.Gauge(document.getElementById('chart_div')); 84 | 85 | chart.draw(data, options); 86 | 87 | 88 | data.setValue(0, 1, r.memory.percent); 89 | chart.draw(data, options); 90 | 91 | data.setValue(1, 1, r.cpu.percent); 92 | chart.draw(data, options); 93 | 94 | data.setValue(2, 1, r.disk.percent); 95 | chart.draw(data, options); 96 | } 97 | } 98 | 99 | // RENDER CPU Frequency 100 | 101 | let render_frequency = (r) => { 102 | google.charts.load('current', {'packages':['corechart']}); 103 | google.charts.setOnLoadCallback(drawChart); 104 | function drawChart() { 105 | var data = google.visualization.arrayToDataTable( 106 | r.cpu_freq_list 107 | ); 108 | 109 | var options = { 110 | title: `CPU Frequency: max(${r.cpu_max})`, 111 | hAxis: {title: 'CPU', titleTextStyle: {color: '#333'}}, 112 | vAxis: {minValue: 0, maxValue:r.cpu_max} 113 | }; 114 | 115 | var chart = new google.visualization.AreaChart(document.getElementById('cpu_frequency_div')); 116 | chart.draw(data, options); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /frappe_system_monitor/frappe_system_monitor/page/system_monitor/system_monitor.json: -------------------------------------------------------------------------------- 1 | { 2 | "content": null, 3 | "creation": "2022-03-25 23:21:28.029620", 4 | "docstatus": 0, 5 | "doctype": "Page", 6 | "idx": 0, 7 | "modified": "2022-03-25 23:21:28.029620", 8 | "modified_by": "Administrator", 9 | "module": "Frappe System Monitor", 10 | "name": "system-monitor", 11 | "owner": "Administrator", 12 | "page_name": "System Monitor", 13 | "roles": [], 14 | "script": null, 15 | "standard": "Yes", 16 | "style": null, 17 | "system_page": 0, 18 | "title": "System Monitor" 19 | } -------------------------------------------------------------------------------- /frappe_system_monitor/frappe_system_monitor/page/system_monitor/system_monitor.py: -------------------------------------------------------------------------------- 1 | import frappe, psutil, time, platform, os, datetime 2 | 3 | 4 | @frappe.whitelist() 5 | def execute(**kwargs): 6 | res = frappe._dict({}) 7 | if not ('System Manager' in [i.role for i in frappe.get_doc('User', frappe.session.user).roles]): 8 | return res 9 | desctable = frappe.render_template( 10 | "frappe_system_monitor/frappe_system_monitor/page/system_monitor/desctable.html", 11 | context=dict( 12 | name= platform.system(), 13 | release= platform.release(), 14 | running_since=datetime.datetime.fromtimestamp(psutil.boot_time()).strftime("%Y-%m-%d %H:%M:%S"), 15 | 16 | )) 17 | res.desctable = desctable 18 | cpu = frappe._dict({}) 19 | cpu.percent = psutil.cpu_percent(interval=0) 20 | initial_cpu = psutil.cpu_freq(percpu=True) 21 | cpu_max = initial_cpu[0].max 22 | cpu_freq_list = [['CPU']+[str(i) for i in range(1, len(initial_cpu)+1)]] 23 | for i in range(1, len(initial_cpu)+1): 24 | fr = psutil.cpu_freq(percpu=True) 25 | cpu_freq_list.append(['']+[i.current for i in fr]) 26 | time.sleep(0.4) 27 | cpu.cpu_freq_list = cpu_freq_list 28 | cpu.cpu_max = cpu_max 29 | 30 | memory = frappe._dict({}) 31 | disk = frappe._dict({}) 32 | memory.percent = psutil.virtual_memory()[2] 33 | disk.percent = psutil.disk_usage('/')[3] 34 | res.memory = memory 35 | res.cpu = cpu 36 | res.disk = disk 37 | return res 38 | 39 | 40 | @frappe.whitelist(allow_guest=True) 41 | def server_status(**kwargs): 42 | res = frappe._dict({}) 43 | res.platform = platform.system() 44 | res.running_since=datetime.datetime.fromtimestamp(psutil.boot_time()).strftime("%Y-%m-%d %H:%M:%S") 45 | cpu = frappe._dict({}) 46 | cpu.percent = psutil.cpu_percent(interval=0) 47 | initial_cpu = psutil.cpu_freq(percpu=True) 48 | cpu_max = initial_cpu[0].max 49 | cpu_freq_list = [['CPU']+[str(i) for i in range(1, len(initial_cpu)+1)]] 50 | for i in range(1, len(initial_cpu)+1): 51 | fr = psutil.cpu_freq(percpu=True) 52 | cpu_freq_list.append(['']+[i.current for i in fr]) 53 | time.sleep(0.4) 54 | cpu.cpu_freq_list = cpu_freq_list 55 | cpu.cpu_max = cpu_max 56 | 57 | memory = frappe._dict({}) 58 | disk = frappe._dict({}) 59 | memory.percent = psutil.virtual_memory()[2] 60 | disk.percent = psutil.disk_usage('/')[3] 61 | res.memory = memory 62 | res.cpu = cpu 63 | res.disk = disk 64 | return res 65 | -------------------------------------------------------------------------------- /frappe_system_monitor/hooks.py: -------------------------------------------------------------------------------- 1 | from . import __version__ as app_version 2 | 3 | app_name = "frappe_system_monitor" 4 | app_title = "Frappe System Monitor" 5 | app_publisher = "Anthony Emmanuel" 6 | app_description = "System monitor for frappe and ERPNExt" 7 | app_icon = "octicon octicon-file-directory" 8 | app_color = "grey" 9 | app_email = "hackacehuawei@gmail.com" 10 | app_license = "MIT" 11 | 12 | # Includes in 13 | # ------------------ 14 | 15 | # include js, css files in header of desk.html 16 | # app_include_css = "/assets/frappe_system_monitor/css/frappe_system_monitor.css" 17 | # app_include_js = "/assets/frappe_system_monitor/js/frappe_system_monitor.js" 18 | 19 | # include js, css files in header of web template 20 | # web_include_css = "/assets/frappe_system_monitor/css/frappe_system_monitor.css" 21 | # web_include_js = "/assets/frappe_system_monitor/js/frappe_system_monitor.js" 22 | 23 | # include custom scss in every website theme (without file extension ".scss") 24 | # website_theme_scss = "frappe_system_monitor/public/scss/website" 25 | 26 | # include js, css files in header of web form 27 | # webform_include_js = {"doctype": "public/js/doctype.js"} 28 | # webform_include_css = {"doctype": "public/css/doctype.css"} 29 | 30 | # include js in page 31 | # page_js = {"page" : "public/js/file.js"} 32 | 33 | # include js in doctype views 34 | # doctype_js = {"doctype" : "public/js/doctype.js"} 35 | # doctype_list_js = {"doctype" : "public/js/doctype_list.js"} 36 | # doctype_tree_js = {"doctype" : "public/js/doctype_tree.js"} 37 | # doctype_calendar_js = {"doctype" : "public/js/doctype_calendar.js"} 38 | 39 | # Home Pages 40 | # ---------- 41 | 42 | # application home page (will override Website Settings) 43 | # home_page = "login" 44 | 45 | # website user home page (by Role) 46 | # role_home_page = { 47 | # "Role": "home_page" 48 | # } 49 | 50 | # Generators 51 | # ---------- 52 | 53 | # automatically create page for each record of this doctype 54 | # website_generators = ["Web Page"] 55 | 56 | # Installation 57 | # ------------ 58 | 59 | # before_install = "frappe_system_monitor.install.before_install" 60 | # after_install = "frappe_system_monitor.install.after_install" 61 | 62 | # Uninstallation 63 | # ------------ 64 | 65 | # before_uninstall = "frappe_system_monitor.uninstall.before_uninstall" 66 | # after_uninstall = "frappe_system_monitor.uninstall.after_uninstall" 67 | 68 | # Desk Notifications 69 | # ------------------ 70 | # See frappe.core.notifications.get_notification_config 71 | 72 | # notification_config = "frappe_system_monitor.notifications.get_notification_config" 73 | 74 | # Permissions 75 | # ----------- 76 | # Permissions evaluated in scripted ways 77 | 78 | # permission_query_conditions = { 79 | # "Event": "frappe.desk.doctype.event.event.get_permission_query_conditions", 80 | # } 81 | # 82 | # has_permission = { 83 | # "Event": "frappe.desk.doctype.event.event.has_permission", 84 | # } 85 | 86 | # DocType Class 87 | # --------------- 88 | # Override standard doctype classes 89 | 90 | # override_doctype_class = { 91 | # "ToDo": "custom_app.overrides.CustomToDo" 92 | # } 93 | 94 | # Document Events 95 | # --------------- 96 | # Hook on document methods and events 97 | 98 | # doc_events = { 99 | # "*": { 100 | # "on_update": "method", 101 | # "on_cancel": "method", 102 | # "on_trash": "method" 103 | # } 104 | # } 105 | 106 | # Scheduled Tasks 107 | # --------------- 108 | 109 | # scheduler_events = { 110 | # "all": [ 111 | # "frappe_system_monitor.tasks.all" 112 | # ], 113 | # "daily": [ 114 | # "frappe_system_monitor.tasks.daily" 115 | # ], 116 | # "hourly": [ 117 | # "frappe_system_monitor.tasks.hourly" 118 | # ], 119 | # "weekly": [ 120 | # "frappe_system_monitor.tasks.weekly" 121 | # ] 122 | # "monthly": [ 123 | # "frappe_system_monitor.tasks.monthly" 124 | # ] 125 | # } 126 | 127 | # Testing 128 | # ------- 129 | 130 | # before_tests = "frappe_system_monitor.install.before_tests" 131 | 132 | # Overriding Methods 133 | # ------------------------------ 134 | # 135 | # override_whitelisted_methods = { 136 | # "frappe.desk.doctype.event.event.get_events": "frappe_system_monitor.event.get_events" 137 | # } 138 | # 139 | # each overriding function accepts a `data` argument; 140 | # generated from the base implementation of the doctype dashboard, 141 | # along with any modifications made in other Frappe apps 142 | # override_doctype_dashboards = { 143 | # "Task": "frappe_system_monitor.task.get_dashboard_data" 144 | # } 145 | 146 | # exempt linked doctypes from being automatically cancelled 147 | # 148 | # auto_cancel_exempted_doctypes = ["Auto Repeat"] 149 | 150 | 151 | # User Data Protection 152 | # -------------------- 153 | 154 | user_data_fields = [ 155 | { 156 | "doctype": "{doctype_1}", 157 | "filter_by": "{filter_by}", 158 | "redact_fields": ["{field_1}", "{field_2}"], 159 | "partial": 1, 160 | }, 161 | { 162 | "doctype": "{doctype_2}", 163 | "filter_by": "{filter_by}", 164 | "partial": 1, 165 | }, 166 | { 167 | "doctype": "{doctype_3}", 168 | "strict": False, 169 | }, 170 | { 171 | "doctype": "{doctype_4}" 172 | } 173 | ] 174 | 175 | # Authentication and authorization 176 | # -------------------------------- 177 | 178 | # auth_hooks = [ 179 | # "frappe_system_monitor.auth.validate" 180 | # ] 181 | 182 | -------------------------------------------------------------------------------- /frappe_system_monitor/modules.txt: -------------------------------------------------------------------------------- 1 | Frappe System Monitor -------------------------------------------------------------------------------- /frappe_system_monitor/patches.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mymi14s/frappe_system_monitor/4aabbe32663464e6db24ab9e597c5f2bee576eed/frappe_system_monitor/patches.txt -------------------------------------------------------------------------------- /frappe_system_monitor/public/build.json: -------------------------------------------------------------------------------- 1 | { 2 | 3 | "js/desk.min.js": [ 4 | 5 | "templates/pages/system_monitor.html", 6 | ] 7 | 8 | } 9 | -------------------------------------------------------------------------------- /frappe_system_monitor/public/js/loader.js: -------------------------------------------------------------------------------- 1 | (function(){/* 2 | 3 | Copyright The Closure Library Authors. 4 | SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 'use strict';var l;function aa(a){var b=0;return function(){return b>>0)+"_",e=0;return b}); 9 | q("Symbol.iterator",function(a){if(a)return a;a=Symbol("Symbol.iterator");for(var b="Array Int8Array Uint8Array Uint8ClampedArray Int16Array Uint16Array Int32Array Uint32Array Float32Array Float64Array".split(" "),c=0;c=e}});function na(a,b,c){a instanceof String&&(a=String(a));for(var d=a.length,e=0;e=g}});q("String.prototype.repeat",function(a){return a?a:function(b){var c=v(this,null,"repeat");if(0>b||1342177279>>=1)c+=c;return d}}); 25 | function oa(a,b){a instanceof String&&(a+="");var c=0,d=!1,e={next:function(){if(!d&&cc&&(c=Math.max(c+e,0));cc?Math.max(g+c,0):Math.min(c,g);d=0>d?Math.max(g+d,0):Math.min(d,g);e=0>e?Math.max(g+e,0):Math.min(e,g);if(cd;)--e in this?this[--c]=this[e]:delete this[--c];return this}}); 36 | q("Array.prototype.entries",function(a){return a?a:function(){return oa(this,function(b,c){return[b,c]})}});q("Array.prototype.fill",function(a){return a?a:function(b,c,d){var e=this.length||0;0>c&&(c=Math.max(0,e+c));if(null==d||d>e)d=e;d=Number(d);0>d&&(d=Math.max(0,e+d));for(c=Number(c||0);cb?-c:c}});q("Math.log1p",function(a){return a?a:function(b){b=Number(b);if(.25>b&&-.25b?-c:c}});q("Math.clz32",function(a){return a?a:function(b){b=Number(b)>>>0;if(0===b)return 32;var c=0;0===(b&4294901760)&&(b<<=16,c+=16);0===(b&4278190080)&&(b<<=8,c+=8);0===(b&4026531840)&&(b<<=4,c+=4);0===(b&3221225472)&&(b<<=2,c+=2);0===(b&2147483648)&&c++;return c}}); 40 | q("Math.cosh",function(a){if(a)return a;var b=Math.exp;return function(c){c=Number(c);return(b(c)+b(-c))/2}});q("Math.expm1",function(a){return a?a:function(b){b=Number(b);if(.25>b&&-.25arguments.length)return arguments.length?Math.abs(arguments[0]):0;var c,d,e;for(c=e=0;ce){if(!e)return e;for(c=d=0;c>>16&65535)*e+d*(c>>>16&65535)<<16>>>0)|0}});q("Math.log10",function(a){return a?a:function(b){return Math.log(b)/Math.LN10}});q("Math.log2",function(a){return a?a:function(b){return Math.log(b)/Math.LN2}});q("Math.sign",function(a){return a?a:function(b){b=Number(b);return 0===b||isNaN(b)?b:0b?-c:c}});q("Math.trunc",function(a){return a?a:function(b){b=Number(b);if(isNaN(b)||Infinity===b||-Infinity===b||0===b)return b;var c=Math.floor(Math.abs(b));return 0>b?-c:c}});q("Number.EPSILON",function(){return Math.pow(2,-52)}); 44 | q("Number.MAX_SAFE_INTEGER",function(){return 9007199254740991});q("Number.MIN_SAFE_INTEGER",function(){return-9007199254740991});q("Number.isFinite",function(a){return a?a:function(b){return"number"!==typeof b?!1:!isNaN(b)&&Infinity!==b&&-Infinity!==b}});q("Number.isInteger",function(a){return a?a:function(b){return Number.isFinite(b)?b===Math.floor(b):!1}});q("Number.isNaN",function(a){return a?a:function(b){return"number"===typeof b&&isNaN(b)}}); 45 | q("Number.isSafeInteger",function(a){return a?a:function(b){return Number.isInteger(b)&&Math.abs(b)<=Number.MAX_SAFE_INTEGER}});q("Number.parseFloat",function(a){return a||parseFloat});q("Number.parseInt",function(a){return a||parseInt});q("Object.entries",function(a){return a?a:function(b){var c=[],d;for(d in b)u(b,d)&&c.push([d,b[d]]);return c}}); 46 | q("Object.fromEntries",function(a){return a?a:function(b){var c={};if(!(Symbol.iterator in b))throw new TypeError(""+b+" is not iterable");b=b[Symbol.iterator].call(b);for(var d=b.next();!d.done;d=b.next()){d=d.value;if(Object(d)!==d)throw new TypeError("iterable for fromEntries should yield objects");c[d[0]]=d[1]}return c}});q("Object.getOwnPropertySymbols",function(a){return a?a:function(){return[]}}); 47 | q("Reflect.ownKeys",function(a){return a?a:function(b){var c=[],d=Object.getOwnPropertyNames(b);b=Object.getOwnPropertySymbols(b);for(var e=0;e=arguments.length)return b[c];var e=qa(b,c);if(e)return e.get?e.get.call(d):e.value}});q("Reflect.has",function(a){return a?a:function(b,c){return c in b}}); 53 | q("Reflect.isExtensible",function(a){return a?a:"function"==typeof Object.isExtensible?Object.isExtensible:function(){return!0}});q("Reflect.preventExtensions",function(a){return a?a:"function"!=typeof Object.preventExtensions?function(){return!1}:function(b){Object.preventExtensions(b);return!Object.isExtensible(b)}}); 54 | q("Reflect.set",function(a){return a?a:function(b,c,d,e){var g=qa(b,c);return g?g.set?(g.set.call(3e||56319b||57343e||1114111=e?c+=String.fromCharCode(e):(e-=65536,c+=String.fromCharCode(e>>>10&1023|55296),c+=String.fromCharCode(e&1023|56320))}return c}}); 59 | q("String.prototype.matchAll",function(a){return a?a:function(b){if(b instanceof RegExp&&!b.global)throw new TypeError("RegExp passed into String.prototype.matchAll() must have global tag.");var c=new RegExp(b,b instanceof RegExp?void 0:"g"),d=this,e=!1,g={next:function(){if(e)return{value:void 0,done:!0};var f=c.exec(d);if(!f)return e=!0,{value:void 0,done:!0};""===f[0]&&(c.lastIndex+=1);return{value:f,done:!1}}};g[Symbol.iterator]=function(){return g};return g}}); 60 | function ra(a,b){a=void 0!==a?String(a):" ";return 0a.length?"&":"")+encodeURIComponent(d)+"="+encodeURIComponent(String(f)))}}return b};var Ma=Array.prototype.some?function(a,b){return Array.prototype.some.call(a,b,void 0)}:function(a,b){for(var c=a.length,d="string"===typeof a?a.split(""):a,e=0;e=d.g.length)throw Wa;var g=d.g[b++];return a?g:d.h[g]};e.next=e.g.bind(e);return e};function Q(a,b){return Object.prototype.hasOwnProperty.call(a,b)};var ab=/^(?:([^:/?#.]+):)?(?:\/\/(?:([^\\/?#]*)@)?([^\\/?#]*?)(?::([0-9]+))?(?=[\\/?#]|$))?([^?#]+)?(?:\?([^#]*))?(?:#([\s\S]*))?$/;function bb(a,b){if(a){a=a.split("&");for(var c=0;cb)throw Error("Bad port number "+b);a.v=b}else a.v=null}function fb(a,b,c){b instanceof R?(a.i=b,nb(a.i,a.l)):(c||(b=ib(b,ob)),a.i=new R(b,a.l))} 108 | function hb(a,b){return a?b?decodeURI(a.replace(/%25/g,"%2525")):decodeURIComponent(a):""}function ib(a,b,c){return"string"===typeof a?(a=encodeURI(a).replace(b,pb),c&&(a=a.replace(/%25([0-9a-fA-F]{2})/g,"%$1")),a):null}function pb(a){a=a.charCodeAt(0);return"%"+(a>>4&15).toString(16)+(a&15).toString(16)}var jb=/[#\/\?@]/g,lb=/[#\?:]/g,kb=/[#\?]/g,ob=/[#\?@]/g,mb=/#/g;function R(a,b){this.h=this.g=null;this.i=a||null;this.j=!!b} 109 | function S(a){a.g||(a.g=new Za,a.h=0,a.i&&bb(a.i,function(b,c){a.add(decodeURIComponent(b.replace(/\+/g," ")),c)}))}l=R.prototype;l.add=function(a,b){S(this);this.i=null;a=T(this,a);var c=this.g.get(a);c||this.g.set(a,c=[]);c.push(b);this.h+=1;return this};function qb(a,b){S(a);b=T(a,b);a.g.has(b)&&(a.i=null,a.h-=a.g.get(b).length,a=a.g,Q(a.h,b)&&(delete a.h[b],--a.size,a.i++,a.g.length>2*a.size&&$a(a)))}function rb(a,b){S(a);b=T(a,b);return a.g.has(b)} 110 | l.forEach=function(a,b){S(this);this.g.forEach(function(c,d){c.forEach(function(e){a.call(b,e,d,this)},this)},this)};l.G=function(){S(this);for(var a=this.g.H(),b=this.g.G(),c=[],d=0;da.h&&(a.h++,b.next=a.g,a.g=b)};var yb; 114 | function zb(){var a=A.MessageChannel;"undefined"===typeof a&&"undefined"!==typeof window&&window.postMessage&&window.addEventListener&&-1==L.indexOf("Presto")&&(a=function(){var e=ub(document,"IFRAME");e.style.display="none";document.documentElement.appendChild(e);var g=e.contentWindow;e=g.document;e.open();e.close();var f="callImmediate"+Math.random(),h="file:"==g.location.protocol?"*":g.location.protocol+"//"+g.location.host;e=D(function(k){if(("*"==h||k.origin==h)&&k.data==f)this.port1.onmessage()},this); 115 | g.addEventListener("message",e,!1);this.port1={};this.port2={postMessage:function(){g.postMessage(f,h)}}});if("undefined"!==typeof a&&-1==L.indexOf("Trident")&&-1==L.indexOf("MSIE")){var b=new a,c={},d=c;b.port1.onmessage=function(){if(void 0!==c.next){c=c.next;var e=c.P;c.P=null;e()}};return function(e){d.next={P:e};d=d.next;b.port2.postMessage(0)}}return function(e){A.setTimeout(e,0)}};function Ab(a){A.setTimeout(function(){throw a;},0)};function Bb(){this.h=this.g=null}Bb.prototype.add=function(a,b){var c=Cb.get();c.set(a,b);this.h?this.h.next=c:this.g=c;this.h=c};function Db(){var a=Eb,b=null;a.g&&(b=a.g,a.g=a.g.next,a.g||(a.h=null),b.next=null);return b}var Cb=new wb(function(){return new Fb},function(a){return a.reset()});function Fb(){this.next=this.g=this.h=null}Fb.prototype.set=function(a,b){this.h=a;this.g=b;this.next=null};Fb.prototype.reset=function(){this.next=this.g=this.h=null};function Gb(a,b){Hb||Ib();Jb||(Hb(),Jb=!0);Eb.add(a,b)}var Hb;function Ib(){if(A.Promise&&A.Promise.resolve){var a=A.Promise.resolve(void 0);Hb=function(){a.then(Kb)}}else Hb=function(){var b=Kb;"function"!==typeof A.setImmediate||A.Window&&A.Window.prototype&&-1==L.indexOf("Edge")&&A.Window.prototype.setImmediate==A.setImmediate?(yb||(yb=zb()),yb(b)):A.setImmediate(b)}}var Jb=!1,Eb=new Bb;function Kb(){for(var a;a=Db();){try{a.h.call(a.g)}catch(b){Ab(b)}xb(Cb,a)}Jb=!1};function Lb(a){if(!a)return!1;try{return!!a.$goog_Thenable}catch(b){return!1}};function U(a){this.g=0;this.s=void 0;this.j=this.h=this.i=null;this.l=this.o=!1;if(a!=C)try{var b=this;a.call(void 0,function(c){V(b,2,c)},function(c){V(b,3,c)})}catch(c){V(this,3,c)}}function Mb(){this.next=this.i=this.h=this.j=this.g=null;this.l=!1}Mb.prototype.reset=function(){this.i=this.h=this.j=this.g=null;this.l=!1};var Nb=new wb(function(){return new Mb},function(a){a.reset()});function Ob(a,b,c){var d=Nb.get();d.j=a;d.h=b;d.i=c;return d} 116 | U.prototype.then=function(a,b,c){return Pb(this,"function"===typeof a?a:null,"function"===typeof b?b:null,c)};U.prototype.$goog_Thenable=!0;U.prototype.cancel=function(a){if(0==this.g){var b=new Qb(a);Gb(function(){Rb(this,b)},this)}};function Rb(a,b){if(0==a.g)if(a.i){var c=a.i;if(c.h){for(var d=0,e=null,g=null,f=c.h;f&&(f.l||(d++,f.g==a&&(e=f),!(e&&1=b.v&&b.cancel())}this.J?this.J.call(this.I,this):this.C=!0;this.i||(a=new ac(this),bc(this),cc(this,!1,a))}};W.prototype.D=function(a,b){this.s=!1;cc(this,a,b)};function cc(a,b,c){a.i=!0;a.h=c;a.j=!b;dc(a)} 126 | function bc(a){if(a.i){if(!a.C)throw new ec(a);a.C=!1}}function fc(a,b,c,d){a.l.push([b,c,d]);a.i&&dc(a)}W.prototype.then=function(a,b,c){var d,e,g=new U(function(f,h){e=f;d=h});fc(this,e,function(f){f instanceof ac?g.cancel():d(f)});return g.then(a,b,c)};W.prototype.$goog_Thenable=!0;function gc(a){return Ma(a.l,function(b){return"function"===typeof b[1]})} 127 | function dc(a){if(a.o&&a.i&&gc(a)){var b=a.o,c=hc[b];c&&(A.clearTimeout(c.g),delete hc[b]);a.o=0}a.g&&(a.g.v--,delete a.g);b=a.h;for(var d=c=!1;a.l.length&&!a.s;){var e=a.l.shift(),g=e[0],f=e[1];e=e[2];if(g=a.j?f:g)try{var h=g.call(e||a.I,b);void 0!==h&&(a.j=a.j&&(h==b||h instanceof Error),a.h=b=h);if(Lb(b)||"function"===typeof A.Promise&&b instanceof A.Promise)d=!0,a.s=!0}catch(k){b=k,a.j=!0,gc(a)||(c=!0)}}a.h=b;d&&(h=D(a.D,a,!0),d=D(a.D,a,!1),b instanceof W?(fc(b,h,d),b.L=!0):b.then(h,d));c&&(b= 128 | new ic(b),hc[b.g]=b,a.o=b.g)}function ec(){F.call(this)}va(ec,F);ec.prototype.message="Deferred has already fired";ec.prototype.name="AlreadyCalledError";function ac(){F.call(this)}va(ac,F);ac.prototype.message="Deferred was canceled";ac.prototype.name="CanceledError";function ic(a){this.g=A.setTimeout(D(this.i,this),0);this.h=a}ic.prototype.i=function(){delete hc[this.g];throw this.h;};var hc={};function jc(a){var b;return(b=(a||document).getElementsByTagName("HEAD"))&&0!==b.length?b[0]:a.documentElement}function $b(){if(this&&this.U){var a=this.U;a&&"SCRIPT"==a.tagName&&kc(a,!0,this.W)}}function kc(a,b,c){null!=c&&A.clearTimeout(c);a.onload=C;a.onerror=C;a.onreadystatechange=C;b&&window.setTimeout(function(){a&&a.parentNode&&a.parentNode.removeChild(a)},0)}function lc(a,b){var c="Jsloader error (code #"+a+")";b&&(c+=": "+b);F.call(this,c);this.code=a}va(lc,F);/* 129 | 130 | Copyright 2021 Google LLC 131 | This code is released under the MIT license. 132 | SPDX-License-Identifier: MIT 133 | */ 134 | function mc(a){return Ka(a.format,a.ba,a.ya||{})} 135 | function nc(a){var b={timeout:3E4,attributes:{async:!1,defer:!1}},c=b.document||document,d=Ca(a).toString(),e=ub((new vb(c)).g,"SCRIPT"),g={U:e,W:void 0},f=new W(g),h=null,k=null!=b.timeout?b.timeout:5E3;0Hello 2 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | License: MIT -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | # frappe -- https://github.com/frappe/frappe is installed via 'bench init' -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup, find_packages 2 | 3 | with open("requirements.txt") as f: 4 | install_requires = f.read().strip().split("\n") 5 | 6 | # get version from __version__ variable in frappe_system_monitor/__init__.py 7 | from frappe_system_monitor import __version__ as version 8 | 9 | setup( 10 | name="frappe_system_monitor", 11 | version=version, 12 | description="System monitor for frappe and ERPNExt", 13 | author="Anthony Emmanuel", 14 | author_email="hackacehuawei@gmail.com", 15 | packages=find_packages(), 16 | zip_safe=False, 17 | include_package_data=True, 18 | install_requires=install_requires 19 | ) 20 | --------------------------------------------------------------------------------