diff options
author | George Moschovitis <george.moschovitis@gmail.com> | 2019-01-28 12:27:42 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-01-28 12:27:42 +0200 |
commit | b6ce8175451c70db785f36f31b1d26c23f9f6979 (patch) | |
tree | 8e789a92062d1411a1780be52db88fd47cd8c89e | |
parent | afe8af3372eaa6862207ad3b769b5f5c7355e21c (diff) |
Cloud Sign-In (#5095)
* Manually merged changes from old hub-support branch, tracking #131
Call claim url #4771
Claim ui improvements #4771
Cleanup
Implement Sign Out
Introduced sign-in modal #3990
Added sign-in button
More work on the iframe trick
More work
More work on the logic, removed old obsolete stuff
Close modal
Implement account menu
Minor rename
Renamed my-netdata to My Agents
Show migrate button
Collect known agents
Work on migrateRegistryDidClick
Minor
Actually show agents from netdata cloud in the menu
Some cleanup
Keep all the alternate_urls for each agent
Fix for tooltips over SignIn/AccountMenu
* Actually use NETDATA.registry.cloudBaseURL
Tricky!
* Hide switch identity when signed-in #153
* Manually merged changes from old hub-support branch, tracking #131
Call claim url #4771
Claim ui improvements #4771
Cleanup
Implement Sign Out
Introduced sign-in modal #3990
Added sign-in button
More work on the iframe trick
More work
More work on the logic, removed old obsolete stuff
Close modal
Implement account menu
Minor rename
Renamed my-netdata to My Agents
Show migrate button
Collect known agents
Work on migrateRegistryDidClick
Minor
Actually show agents from netdata cloud in the menu
Some cleanup
Keep all the alternate_urls for each agent
Fix for tooltips over SignIn/AccountMenu
* Actually use NETDATA.registry.cloudBaseURL
Tricky!
* Hide switch identity when signed-in #153
* Cleanup
* Refresh menu on sign-in
* Disable cloud functionality if cloud base url is not set.
This wll allow the merging of the branch into master, so we can avoid nasty rebases.
* Updated to use the latest API endpoints
* Fixed a couple of LGTM warnings
* Improved migration algorithm, some cleanup.
* Update My-Netdata menu on sign-out
* Minor
* Replaced modal with window
* Update the My-Agents menu after migration, cleanup
* Make the agent work after switching cloudBaseURL, cleanup
* Introduced event tracing for analytics
* Minor
* Removed GA
* Fixed error reported by LGTM
* Only send the diff when syncing agents to ameliorate the load on the backend, cleanup
* Reverted My-Netdata name, added some logging
* Add Netdata Cloud menu item
* Minor
* Use the merge: false option and a fix
* Added loading message in my-netdata menu
* Show error if we cannot connect to netdata.cloud
* Minor
* Implemented deleteCloudKnownAgentURL api call, use it in my-netdata menu.
* Removed menu entry
* Disable my-netdata menu if user is not signed-in and using the global registry
* Stop accessing the registry if it's not used.
* Mask the agent url if the registry is in 'disabled' mode
* Filter masked urls
* Improved filtering of masked urls
* Try to eagerly initialize the account ui to improve perceived performance
* Minor
* Don't search for other people's urls in cloud-enabled mode.
* Added basic my-netdata filtering
* Filter streamed host, aesthetic fixes
* Minor
* Some improvements of the filter ui
* Removed What is this
* Added placeholder to input, other fixes #240
* Show message if no databases match filter criteria
* Fixed bug where agent lists where not merged
* Minor
* Hide modal if it redirects to self.
* autocomplete off for filter input
* Enable delete for custom registries, don't show error if delete fails
* Filter agents without urls
* Fix LGTM warning
* Minor
* Concatenate at client side, used the faster merge: false path
* Added a clear button to the filter for extra usability
* Minor
* Minor
* Improvements for small screens (more needed)
* Combined my-netdata menu and hostname
* Re-enabled registry masking
* Show agent-filter only when signed-in
* Improved syncAgents
* Don't mask if using custom registry
* Reject agents with empty urls
* Filter valid agents
* Fixed a couple of bugs
* Applied Chris' fixes
* Fix in registry.c
* Cleanup
* Only sync once
* Implemented forceSync
* Added what is this
* sso, wip
* Working SSO sign-in/sign-out, cleanup
* Added Chris' patch
* Added a modal that explains what synchronize is doing
* Use sso-agent
* Use origin as query param in sign-in
* iframe -> origin
* Pass machine_guid to sso
* Make sure that the current netdata agent is synchronized hub#262
* Normalize originURL
* Reenable tryFastInitCloud()
* Updated to the latest endpoints
* Support synchronizing to multiple cloud accounts
* Set default cloud base url to netdata.cloud
* Fix filter issues with Firefox
* Fix for double tooltip on sign-in
* Show known servers in console for debugging purposes
* Don't block on errors to delete from registry when signed in
* Disable tryFastInitCloud
* Improved styling for filter input
* Improved styling in my-netdata menu
* Display the registry url in the sync-registry modal
* agents -> nodes in texts
* Support for sso-precheck
* Do not implicitly synchronize custom registries.
* Improvement to syncAgents (more coming)
* More fixes
* Don't sign in users with private registries if they don't consent on the sync
* Set netdataRegistryAfterMs = 0
* Don't pass url to sso-agent
* Added Chris' patch to alarm-notify
* Refactored syncAgent/mergeAgents, make sure current Agent is synced on sign-in.
* Fix for LGTM warning
* Minor
* Fix for a XSS warning
* Extra check for dataLayer
-rw-r--r-- | .gitignore | 3 | ||||
-rwxr-xr-x | health/notifications/alarm-notify.sh.in | 22 | ||||
-rw-r--r-- | registry/registry.c | 4 | ||||
-rw-r--r-- | registry/registry_init.c | 4 | ||||
-rw-r--r-- | web/gui/dashboard.js | 49 | ||||
-rw-r--r-- | web/gui/goto-host-from-alarm.html | 9 | ||||
-rw-r--r-- | web/gui/index.html | 107 | ||||
-rw-r--r-- | web/gui/main.css | 61 | ||||
-rw-r--r-- | web/gui/main.js | 807 | ||||
-rw-r--r-- | web/gui/src/dashboard.js/options.js | 2 | ||||
-rw-r--r-- | web/gui/src/dashboard.js/registry.js | 47 |
11 files changed, 1004 insertions, 111 deletions
diff --git a/.gitignore b/.gitignore index a4f0bffd25..5af81f00af 100644 --- a/.gitignore +++ b/.gitignore @@ -156,3 +156,6 @@ python.d/python-modules-installer.sh docs/generator/src docs/generator/build docs/generator/mkdocs.yml + +netdata-updater.sh +.environment.sh diff --git a/health/notifications/alarm-notify.sh.in b/health/notifications/alarm-notify.sh.in index 9fca62711a..b96ab52f79 100755 --- a/health/notifications/alarm-notify.sh.in +++ b/health/notifications/alarm-notify.sh.in @@ -1809,7 +1809,27 @@ urlencode "${args_host}" >/dev/null; url_host="${REPLY}" urlencode "${chart}" >/dev/null; url_chart="${REPLY}" urlencode "${family}" >/dev/null; url_family="${REPLY}" urlencode "${name}" >/dev/null; url_name="${REPLY}" -goto_url="${NETDATA_REGISTRY_URL}/goto-host-from-alarm.html?host=${url_host}&chart=${url_chart}&family=${url_family}&alarm=${url_name}&alarm_unique_id=${unique_id}&alarm_id=${alarm_id}&alarm_event_id=${event_id}" + +redirect_params="host=${url_host}&chart=${url_chart}&family=${url_family}&alarm=${url_name}&alarm_unique_id=${unique_id}&alarm_id=${alarm_id}&alarm_event_id=${event_id}" +GOTOCLOUD=0 + +if [ "${NETDATA_REGISTRY_URL}" == "https://registry.my-netdata.io" ] ; then + if [ -z "${NETDATA_REGISTRY_UNIQUE_ID}" ] ; then + if [ -f "@registrydir_POST@/netdata.public.unique.id" ]; then + NETDATA_REGISTRY_UNIQUE_ID="$(cat "@registrydir_POST@/netdata.public.unique.id")" + fi + fi + if [ ! -z "${NETDATA_REGISTRY_UNIQUE_ID}" ] ; then + GOTOCLOUD=1 + fi +fi + +if [ ${GOTOCLOUD} -eq 0 ] ; then + goto_url="${NETDATA_REGISTRY_URL}/goto-host-from-alarm.html?${redirect_params}" +else + urlencode "${NETDATA_REGISTRY_URL}/goto-host-from-alarm.html" >/dev/null; url_registrypath="${REPLY}" + goto_url="https://netdata.cloud/alarms/redirect?agentID=${NETDATA_REGISTRY_UNIQUE_ID}®istrypath=${url_registrypath}&${redirect_params}" +fi # the severity of the alarm severity="${status}" diff --git a/registry/registry.c b/registry/registry.c index 67e179a3a9..aaa448c517 100644 --- a/registry/registry.c +++ b/registry/registry.c @@ -81,6 +81,8 @@ static int registry_json_person_url_callback(void *entry, void *data) { struct registry_json_walk_person_urls_callback *c = (struct registry_json_walk_person_urls_callback *)data; struct web_client *w = c->w; + if (!strcmp(pu->url->url,"***")) return 0; + if(unlikely(c->count++)) buffer_strcat(w->response.data, ","); @@ -97,6 +99,8 @@ static int registry_json_machine_url_callback(void *entry, void *data) { struct web_client *w = c->w; REGISTRY_MACHINE *m = c->m; + if (!strcmp(mu->url->url,"***")) return 1; + if(unlikely(c->count++)) buffer_strcat(w->response.data, ","); diff --git a/registry/registry_init.c b/registry/registry_init.c index b8af0ad869..3cf140deeb 100644 --- a/registry/registry_init.c +++ b/registry/registry_init.c @@ -37,10 +37,12 @@ int registry_init(void) { registry.persons_expiration = config_get_number(CONFIG_SECTION_REGISTRY, "registry expire idle persons days", 365) * 86400; registry.registry_domain = config_get(CONFIG_SECTION_REGISTRY, "registry domain", ""); registry.registry_to_announce = config_get(CONFIG_SECTION_REGISTRY, "registry to announce", "https://registry.my-netdata.io"); - registry.cloud_base_url = config_get(CONFIG_SECTION_CLOUD, "cloud base url", "https://netdata.cloud"); registry.hostname = config_get(CONFIG_SECTION_REGISTRY, "registry hostname", netdata_configured_hostname); registry.verify_cookies_redirects = config_get_boolean(CONFIG_SECTION_REGISTRY, "verify browser cookies support", 1); + // netdata.cloud configuration, if cloud_base_url == "", cloud functionality is disabled. + registry.cloud_base_url = config_get(CONFIG_SECTION_CLOUD, "cloud base url", "https://netdata.cloud"); + setenv("NETDATA_REGISTRY_HOSTNAME", registry.hostname, 1); setenv("NETDATA_REGISTRY_URL", registry.registry_to_announce, 1); diff --git a/web/gui/dashboard.js b/web/gui/dashboard.js index d066da2f52..71d12e590b 100644 --- a/web/gui/dashboard.js +++ b/web/gui/dashboard.js @@ -1246,7 +1246,7 @@ if (typeof netdataShowAlarms === 'undefined') { } if (typeof netdataRegistryAfterMs !== 'number' || netdataRegistryAfterMs < 0) { - netdataRegistryAfterMs = 1500; + netdataRegistryAfterMs = 0; // 1500; } if (typeof netdataRegistry === 'undefined') { @@ -9677,6 +9677,7 @@ NETDATA.alarms = { NETDATA.registry = { server: null, // the netdata registry server + isCloudEnabled: false,// is netdata.cloud functionality enabled? cloudBaseURL: null, // the netdata cloud base url person_guid: null, // the unique ID of this browser / user machine_guid: null, // the unique ID the netdata server that served dashboard.js @@ -9685,8 +9686,17 @@ NETDATA.registry = { machines_array: null, // the user's other URLs in an array person_urls: null, + MASKED_DATA: "***", + + isUsingGlobalRegistry: function() { + return NETDATA.registry.server == "https://registry.my-netdata.io"; + }, + + isRegistryEnabled: function() { + return !(NETDATA.registry.isUsingGlobalRegistry() || isSignedIn()) + }, + parsePersonUrls: function (person_urls) { - // console.log(person_urls); NETDATA.registry.person_urls = person_urls; if (person_urls) { @@ -9739,14 +9749,21 @@ NETDATA.registry = { NETDATA.registry.hello(NETDATA.serverDefault, function (data) { if (data) { NETDATA.registry.server = data.registry; - NETDATA.registry.cloudBaseURL = data.cloud_base_url; + if (data.cloud_base_url != "") { + NETDATA.registry.isCloudEnabled = true; + NETDATA.registry.cloudBaseURL = data.cloud_base_url; + } else { + NETDATA.registry.isCloudEnabled = false; + NETDATA.registry.cloudBaseURL = ""; + } NETDATA.registry.machine_guid = data.machine_guid; NETDATA.registry.hostname = data.hostname; - if (data.anonymous_statistics) dataLayer.push({"anonymous_statistics" : "true", "machine_guid" : data.machine_guid}); + if (dataLayer) { + if (data.anonymous_statistics) dataLayer.push({"anonymous_statistics" : "true", "machine_guid" : data.machine_guid}); + } NETDATA.registry.access(2, function (person_urls) { NETDATA.registry.parsePersonUrls(person_urls); - - }); + }); } }); }, @@ -9789,13 +9806,25 @@ NETDATA.registry = { }, access: function (max_redirects, callback) { + let name = NETDATA.registry.MASKED_DATA; + let url = NETDATA.registry.MASKED_DATA; + + if (!NETDATA.registry.isUsingGlobalRegistry()) { + // If the user is using a private registry keep sending identifiable + // data. + name = NETDATA.registry.hostname; + url = NETDATA.serverDefault; + } + + console.log("ACCESS", name, url); + // send ACCESS to a netdata registry: // 1. it lets it know we are accessing a netdata server (its machine GUID and its URL) // 2. it responds with a list of netdata servers we know // the registry identifies us using a cookie it sets the first time we access it // the registry may respond with a redirect URL to send us to another registry $.ajax({ - url: NETDATA.registry.server + '/api/v1/registry?action=access&machine=' + NETDATA.registry.machine_guid + '&name=' + encodeURIComponent(NETDATA.registry.hostname) + '&url=' + encodeURIComponent(NETDATA.serverDefault), // + '&visible_url=' + encodeURIComponent(document.location), + url: NETDATA.registry.server + '/api/v1/registry?action=access&machine=' + NETDATA.registry.machine_guid + '&name=' + encodeURIComponent(name) + '&url=' + encodeURIComponent(url), // + '&visible_url=' + encodeURIComponent(document.location), async: true, cache: false, headers: { @@ -9827,14 +9856,14 @@ NETDATA.registry = { return callback(null); } } - } - else { + } else { if (typeof data.person_guid === 'string') { NETDATA.registry.person_guid = data.person_guid; } if (typeof callback === 'function') { - return callback(data.urls); + const urls = data.urls.filter((u) => u[1] !== NETDATA.registry.MASKED_DATA); + return callback(urls); } } }) diff --git a/web/gui/goto-host-from-alarm.html b/web/gui/goto-host-from-alarm.html index 5eb66b5d0c..eb1d4839ba 100644 --- a/web/gui/goto-host-from-alarm.html +++ b/web/gui/goto-host-from-alarm.html @@ -2,16 +2,21 @@ <!-- SPDX-License-Identifier: GPL-3.0-or-later --> <html lang="en"> <head> + <script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': + new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], + j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= + 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); + })(window,document,'script','dataLayer','GTM-N6CBMJD'); + dataLayer.push({"anonymous_statistics" : "false"}); + </script> <title>Goto a host you know...</title> <meta name="application-name" content="netdata"> - <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> - </head> <script> var netdataRegistry = true; diff --git a/web/gui/index.html b/web/gui/index.html index 8cae72c51a..6034cf7bd0 100644 --- a/web/gui/index.html +++ b/web/gui/index.html @@ -88,18 +88,23 @@ </script> <nav class="navbar navbar-default navbar-fixed-top" role="banner"> <div class="container"> - <nav id="mynetdata_nav" class="collapse navbar-collapse navbar-left hidden-sm hidden-xs" role="navigation" style="padding-right: 20px;"> + <!-- <nav id="mynetdata_nav" class="collapse navbar-collapse navbar-left" role="navigation" style="padding-right: 20px;"> <ul class="nav navbar-nav"> <li data-placement="right" style="line-height: 50px; margin-right: 15px" title="Netdata Agent"> <img src="images/netdata-logomark.svg" height="32"/> </li> <li class="dropdown" id="myNetdataDropdownParent" title="your other netdata servers" data-toggle="tooltip" data-placement="right"> - <a href="#" class="dropdown-toggle" data-toggle="dropdown">my-netdata <strong class="caret"></strong></a> + <a href="#" id="hostname" class="dropdown-toggle" data-toggle="dropdown">my-netdata <strong class="caret"></strong></a> <div id="my-netdata-dropdown-content" class="dropdown-menu scrollable-menu inpagemenu"> + <div class="agent-item" style="white-space: nowrap"> + <i class="fas fa-hourglass-half"></i> + Loading, please wait... + <div></div> + </div> </div> </li> </ul> - </nav> + </nav> --> <div class="navbar-header"> <button class="navbar-toggle" type="button" data-toggle="collapse" data-target=".navbar-collapse"> <span class="sr-only">Toggle navigation</span> @@ -107,26 +112,56 @@ <span class="icon-bar"></span> <span class="icon-bar"></span> </button> - <a href="/" class="navbar-brand" id="hostname" title="server hostname<br/>click it to reload the dashboard" data-toggle="tooltip" data-placement="bottom">netdata</a> + <!-- <a href="/" class="navbar-brand" id="1hostname" title="server hostname<br/>click it to reload the dashboard" data-toggle="tooltip" data-placement="bottom">netdata</a> --> + <ul class="nav navbar-nav" style="display: inline-block; max-width: 300px"> + <li data-placement="right" class="hidden-xs hidden-sm" style="line-height: 50px; margin-right: 15px" title="Netdata Agent"> + <img src="images/netdata-logomark.svg" height="32"/> + </li> + <li class="dropdown" id="myNetdataDropdownParent" title="your other netdata servers" data-toggle="tooltip" data-placement="right"> + <a href="#" id="hostname" class="dropdown-toggle" data-toggle="dropdown">my-netdata <strong class="caret"></strong></a> + <div id="my-netdata-dropdown-content" class="dropdown-menu scrollable-menu inpagemenu"> + <div class="agent-item" style="white-space: nowrap"> + <i class="fas fa-hourglass-half"></i> + Loading, please wait... + <div></div> + </div> + </div> + </li> + </ul> </div> <nav class="collapse navbar-collapse navbar-right" role="navigation"> <ul class="nav navbar-nav"> <li id="alarmsButton" title="check the health monitoring alarms and their log" data-toggle="tooltip" data-placement="bottom"><a href="#" class="btn" data-toggle="modal" data-target="#alarmsModal"><i class="fas fa-bell"></i> <span class="hidden-sm hidden-md">Alarms </span><span id="alarms_count_badge" class="badge"></span></a></li> <li title="change dashboard settings" data-toggle="tooltip" data-placement="bottom"><a href="#" class="btn" data-toggle="modal" data-target="#optionsModal"><i class="fas fa-cog"></i> <span class="hidden-sm hidden-md">Settings</span></a></li> <li title="check for netdata updates<br/>you should keep your netdata updated" data-toggle="tooltip" data-placement="bottom" class="hidden-sm" id="updateButton"><a href="#" class="btn" data-toggle="modal" data-target="#updateModal"><i class="fas fa-cloud-download-alt"></i> <span class="hidden-sm hidden-md">Update </span><span id="update_badge" class="badge"></span></a></li> - <li title="the netdata wiki home at github<br/>remember to <b>give netdata a <i class="fas fa-star"></i></b> !" data-toggle="tooltip" data-placement="bottom" class="hidden-sm hidden-md"><a href="https://github.com/netdata/netdata/wiki" class="btn" target="_blank"><i class="fab fa-github"></i></a></li> - <li title="follow netdata on twitter" data-toggle="tooltip" data-placement="bottom" class="hidden-sm hidden-md"><a href="https://twitter.com/linuxnetdata" class="btn" target="_blank"><i class="fab fa-twitter"></i></a></li> - <li title="like netdata on facebook" data-toggle="tooltip" data-placement="bottom" class="hidden-sm hidden-md"><a href="https://www.facebook.com/linuxnetdata/" class="btn" target="_blank"><i class="fab fa-facebook"></i></a></li> + <li title="the netdata wiki home at github<br/>remember to <b>give netdata a <i class="fas fa-star"></i></b> !" data-toggle="tooltip" data-placement="bottom" class="hidden-xs hidden-sm hidden-md"><a href="https://github.com/netdata/netdata/wiki" class="btn" target="_blank"><i class="fab fa-github"></i></a></li> + <li title="follow netdata on twitter" data-toggle="tooltip" data-placement="bottom" class="hidden-xs hidden-sm hidden-md"><a href="https://twitter.com/linuxnetdata" class="btn" target="_blank"><i class="fab fa-twitter"></i></a></li> + <li title="like netdata on facebook" data-toggle="tooltip" data-placement="bottom" class="hidden-xs hidden-sm hidden-md"><a href="https://www.facebook.com/linuxnetdata/" class="btn" target="_blank"><i class="fab fa-facebook"></i></a></li> <li title="import / load a netdata snapshot" data-toggle="tooltip" data-placement="bottom" id="loadButton"><a href="#" class="btn" data-toggle="modal" data-target="#loadSnapshotModal"><i class="fas fa-download"></i> <span class="hidden-sm hidden-md hidden-lg">Import</span></a></li> <li title="export / save a netdata snapshot" data-toggle="tooltip" data-placement="bottom" id="saveButton"><a href="#" class="btn" data-toggle="modal" data-target="#saveSnapshotModal"><i class="fas fa-upload"></i> <span class="hidden-sm hidden-md hidden-lg">Export</span></a></li> <li title="print this dashboard to PDF" data-toggle="tooltip" data-placement="bottom" id="printButton"><a href="#" class="btn" data-toggle="modal" data-target="#printPreflightModal"><i class="fas fa-print"></i> <span class="hidden-sm hidden-md hidden-lg">Print</span></a></li> <li title="get help on using the charts" data-toggle="tooltip" data-placement="bottom" class="hidden-sm"><a href="#" class="btn" data-toggle="modal" data-target="#helpModal"><i class="fas fa-question-circle"></i> <span class="hidden-sm hidden-md">Help</span></a></li> - <li class="dropdown hidden-sm hidden-md hidden-lg"> + <li id="account-menu-container" class="dropdown" data-toggle="tooltip"></li> + <!-- + <li class="dropdown hidden-sm hidden-md hidden-lg" id="myNetdataDropdownParent" title="your other netdata servers" data-toggle="tooltip" data-placement="right"> <a href="#" class="dropdown-toggle" data-toggle="dropdown">my-netdata <strong class="caret"></strong></a> + <div id="my-netdata-dropdown-content" class="dropdown-menu scrollable-menu inpagemenu"> + <div class="agent-item" style="white-space: nowrap"> + <i class="fas fa-hourglass-half"></i> + Loading, please wait... + <div></div> + </div> + </div> + </li> + --> + <!-- + <li class="dropdown hidden-sm hidden-md hidden-lg"> + <a href="#" class="dropdown-toggle" data-toggle="dropdown">My Nodes <strong class="caret"></strong></a> <ul id="mynetdata_servers2" class="dropdown-menu scrollable-menu inpagemenu" role="menu"> <li><a href="#" onclick="return false;" style="color: #999;">loading...</a></li> </ul> </li> + --> </ul> </nav> </div> @@ -1186,6 +1221,61 @@ </div> </div> + <div class="modal fade" id="signInModal" tabindex="-1" role="dialog" aria-labelledby="signInModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> + <h4 class="modal-title" id="signInModalLabel">Sign In</h4> + </div> + <div class="modal-body"> + <p> + Signing-in to netdata.cloud will synchronize the list of + your netdata monitored nodes known at registry + <strong><span id="sim-registry"></span></strong>. This + may include server hostnames, urls and identification + GUIDs. + </p> + <p> + After you upgrade all your netdata servers, your private + registry will not be needed any more. + </p> + <p> + Are you sure you want to proceed? + </p> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-success" data-dismiss="modal">Cancel</button> + <a href="#" onclick="explicitlySignIn(); return false;" type="button" class="btn btn-danger">Sign In</a> + </div> + </div> + </div> + </div> + + <div class="modal fade" id="syncRegistryModal" tabindex="-1" role="dialog" aria-labelledby="syncRegistryModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> + <h4 class="modal-title" id="syncRegistryModalLabel">Synchronize netdata.cloud with registry?</h4> + </div> + <div class="modal-body"> + <p> + You are about to synchronize your netdata.cloud account with data from the registry at <strong><span id="sync-registry-modal-registry"></span></strong>. + This may include server hostnames, urls and identification GUIDs. + </p> + <p> + Are you sure you want to proceed? + </p> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-success" data-dismiss="modal">Cancel</button> + <a href="#" onclick="explicitlySyncAgents(); return false;" type="button" class="btn btn-danger">Synchronize</a> + </div> + </div> + </div> + </div> + <div class="modal fade" id="deleteRegistryModal" tabindex="-1" role="dialog" aria-labelledby="deleteRegistryModalLabel"> <div class="modal-dialog" role="document"> <div class="modal-content"> @@ -1275,6 +1365,7 @@ </div> </div> </div> + <iframe id="ssoifrm" width="0" height="0"></iframe> <div id="hiddenDownloadLinks" style="display: none;" hidden></div> <script type="text/javascript" src="dashboard.js?v20181211-1"></script> </body> diff --git a/web/gui/main.css b/web/gui/main.css index ba622b2652..3115b5cf0e 100644 --- a/web/gui/main.css +++ b/web/gui/main.css @@ -532,7 +532,11 @@ body.modal-open { transition: 0s } -/* --- */ +/* -------------------------------------------------------------------------- */ + +#my-netdata-dropdown-content { + width: 500px; +} #my-netdata-dropdown-content a:hover { color: #fff; @@ -609,9 +613,62 @@ body.modal-open { } #my-netdata-dropdown-content.theme-white a { - color: #555; + color: #888; } #my-netdata-dropdown-content.theme-white a:hover { color: #000; } + +#sign-in-iframe { + background-color: #fff; + border: none; +} + +#cloud-menu { +} + +#cloud-menu.dropdown-menu > li > a { + text-align: left; +} + +#my-netdata-menu-filter-input { + color: #fff; + /* background: none; */ + /* border: 1px solid #616161; */ + border: none; + background-color: #4b4f55; + margin: 5px 14px; + width: 90%; + padding: 2px 5px; + outline: none; +} + +#my-netdata-menu-filter-input::placeholder { + opacity: 0.7; +} + +#my-netdata-dropdown-content.theme-white #my-netdata-menu-filter-input { + /* border: 1px solid #ddd; */ + background-color: #e7e7e7; + color: #555; +} + +.filter-control { + position: relative; +} + +.filter-control .filter-control__clear { + cursor: pointer; + position: relative; + left: -36px; +} + +/* .collapse a.btn { + text-align: left; +} */ + +#hostname { + font-size: 18px; +} + diff --git a/web/gui/main.js b/web/gui/main.js index efcd027b4b..3f149bbe5c 100644 --- a/web/gui/main.js +++ b/web/gui/main.js @@ -453,7 +453,7 @@ function saveObjectToClient(data, filename) { saveTextToClient(JSON.stringify(data), filename); } -// -------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // registry call back to render my-netdata menu function toggleExpandIcon(svgEl) { @@ -476,19 +476,6 @@ function toggleAgentItem(e, guid) { } } -// TODO: consider renaming to `truncateString` - -/// Enforces a maximum string length while retaining the prefix and the postfix of -/// the string. -function clipString(str, maxLength) { - if (str.length <= maxLength) { - return str; - } - - const spanLength = Math.floor((maxLength - 3) / 2); - return `${str.substring(0, spanLength)}...${str.substring(str.length - spanLength)}`; -} - // When you stream metrics from netdata to netdata, the recieving netdata now // has multiple host databases. It's own, and multiple mirrored. Mirrored databases // can be accessed with <http://localhost:19999/host/NAME/> @@ -512,10 +499,20 @@ function renderStreamedHosts(options) { return naturalSortCompare(a.hostname, b.hostname); }); + let displayedDatabases = false; + for (var s of sorted) { let url, icon; const hostname = s.hostname; + if (myNetdataMenuFilterValue !== "") { + if (!hostname.includes(myNetdataMenuFilterValue)) { + continue; + } + } + + displayedDatabases = true; + if (hostname === master) { url = `${base}/`; icon = 'home'; @@ -537,11 +534,24 @@ function renderStreamedHosts(options) { ) } + if (!displayedDatabases) { + html += ( + `<div class="info-item"> + <i class="fas fa-filter"></i> + <span style="margin-left: 8px">no databases match the filter criteria.<span> + </div>` + ) + } + return html; } function renderMachines(machinesArray) { - let html = `<div class="info-item">My netdata agents</div>`; + // let html = isSignedIn() + // ? `<div class="info-item">My nodes</div>` + // : `<div class="info-item">My nodes</div>`; + + let html = `<div class="info-item">My nodes</div>`; if (machinesArray === null) { let ret = loadLocalStorage("registryCallback"); @@ -552,6 +562,9 @@ function renderMachines(machinesArray) { } let found = false; + let displayedAgents = false; + + const maskedURL = NETDATA.registry.MASKED_DATA; if (machinesArray) { saveLocalStorage("registryCallback", JSON.stringify(machinesArray)); @@ -563,18 +576,31 @@ function renderMachines(machinesArray) { for (var machine of machines) { found = true; + if (myNetdataMenuFilterValue !== "") { + if (!machine.name.includes(myNetdataMenuFilterValue)) { + continue; + } + } + + displayedAgents = true; + const alternateUrlItems = ( `<div class="agent-alternate-urls agent-${machine.guid} collapsed"> - ${machine.alternate_urls.reduce( - (str, url) => str + ( - `<div class="agent-item agent-item--alternate"> - <div></div> - <a href="${url}" title="${url}">${clipString(url, 64)}</a> - <a href="#" onclick="deleteRegistryModalHandler('${machine.guid}', '${machine.name}', '${url}'); return false;"> - <i class="fas fa-trash" style="color: #777;"></i> - </a> - </div>` - ), + ${machine.alternate_urls.reduce((str, url) => { + if (url === maskedURL) { + return str + } + + return str + ( + `<div class="agent-item agent-item--alternate"> + <div></div> + <a href="${url}" title="${url}">${truncateString(url, 64)}</a> + <a href="#" onclick="deleteRegistryModalHandler('${machine.guid}', '${machine.name}', '${url}'); return false;"> + <i class="fas fa-trash" style="color: #777;"></i> + </a> + </div>` + ) + }, '' )} </div>` @@ -593,13 +619,22 @@ function renderMachines(machinesArray) { ${alternateUrlItems}` ) } |