| Davit Tabidze | 9ca4926 | 2024-07-10 15:51:27 +0400 | [diff] [blame] | 1 | function showTooltip(obj) { |
| 2 | obj.style.visibility = 'visible'; |
| 3 | obj.style.opacity = '1'; |
| 4 | } |
| 5 | function hideTooltip(obj) { |
| 6 | obj.style.visibility = 'hidden'; |
| 7 | obj.style.opacity = '0'; |
| 8 | } |
| 9 | |
| Davit Tabidze | 207ce08 | 2024-04-09 19:15:25 +0400 | [diff] [blame] | 10 | document.addEventListener("DOMContentLoaded", function () { |
| Davit Tabidze | 0007727 | 2024-06-11 20:19:36 +0400 | [diff] [blame] | 11 | document.getElementById('appFrame-default').contentDocument.write("Welcome to the dodo: application launcher, think of it as your desktop environment. You can launch applications from left-hand side dock. You should setup VPN clients on your devices, so you can install applications from Application Manager and access your private network. Instructions on how to do that can be viewed by clicking <b>Help</b> button after hovering over <b>Headscale</b> icon in the dock."); |
| Davit Tabidze | 9ca4926 | 2024-07-10 15:51:27 +0400 | [diff] [blame] | 12 | document.getElementById('appFrame-default').style.backgroundColor = '#d6d6d6'; |
| gio | 33fa9ca | 2024-08-16 10:25:24 +0400 | [diff] [blame] | 13 | initDock(); |
| 14 | setTimeout(reloadDock, 5000); |
| 15 | }); |
| 16 | |
| 17 | function copyToClipboard(elem, text) { |
| 18 | navigator.clipboard.writeText(text); |
| 19 | elem.setAttribute("data-tooltip", "Copied"); |
| 20 | elem.setAttribute("data-placement", "bottom"); |
| 21 | setTimeout(() => { |
| 22 | elem.removeAttribute("data-tooltip"); |
| 23 | elem.removeAttribute("data-placement"); |
| 24 | }, 500); |
| 25 | }; |
| 26 | |
| 27 | function reloadDock() { |
| gio | 1bf0080 | 2024-08-17 12:31:41 +0400 | [diff] [blame] | 28 | fetch("/") |
| 29 | .then((resp) => { |
| 30 | if (resp.ok) { |
| 31 | return resp.text(); |
| 32 | } else { |
| 33 | return undefined; |
| gio | 33fa9ca | 2024-08-16 10:25:24 +0400 | [diff] [blame] | 34 | } |
| gio | 1bf0080 | 2024-08-17 12:31:41 +0400 | [diff] [blame] | 35 | }) |
| 36 | .then((resp) => { |
| 37 | if (!resp) { |
| gio | 33fa9ca | 2024-08-16 10:25:24 +0400 | [diff] [blame] | 38 | return; |
| 39 | } |
| gio | 1bf0080 | 2024-08-17 12:31:41 +0400 | [diff] [blame] | 40 | const tmp = document.createElement("div"); |
| 41 | tmp.innerHTML = resp; |
| 42 | const apps = document.querySelector(".app-list"); |
| 43 | let existing = [...document.querySelectorAll(".app-container")]; |
| 44 | let current = [...tmp.querySelectorAll(".app-container")]; |
| 45 | const getId = (e) => e.getAttribute("id"); |
| 46 | const existingIds = existing.map(getId); |
| 47 | const currentIds = current.map(getId); |
| 48 | existing.forEach((e) => { |
| 49 | const id = getId(e); |
| 50 | if (!currentIds.includes(id)) { |
| 51 | e.classList.add("fadeout"); |
| 52 | setTimeout(() => apps.removeChild(e), 1900); |
| 53 | } |
| 54 | }); |
| 55 | let prevId = undefined; |
| 56 | current.forEach((c) => { |
| 57 | const id = getId(c); |
| 58 | if (existingIds.includes(id)) { |
| 59 | prevId = id; |
| 60 | return; |
| 61 | } |
| 62 | c.classList.add("pulsate"); |
| 63 | if (prevId) { |
| 64 | apps.insertBefore(c, document.getElementById(prevId).nextSibling); |
| 65 | } else { |
| 66 | apps.insertBefore(c, apps.firstChild); |
| 67 | } |
| 68 | prevId = id; |
| 69 | }); |
| 70 | initDock(); |
| 71 | }) |
| 72 | .finally(() => setTimeout(reloadDock, 5000)); |
| gio | 33fa9ca | 2024-08-16 10:25:24 +0400 | [diff] [blame] | 73 | } |
| 74 | |
| 75 | function initDock() { |
| Davit Tabidze | 9ca4926 | 2024-07-10 15:51:27 +0400 | [diff] [blame] | 76 | const icons = document.querySelectorAll(".app-icon"); |
| Davit Tabidze | 0007727 | 2024-06-11 20:19:36 +0400 | [diff] [blame] | 77 | const circle = document.querySelector(".user-circle"); |
| 78 | const tooltipUser = document.querySelector("#tooltip-user"); |
| Davit Tabidze | 9ca4926 | 2024-07-10 15:51:27 +0400 | [diff] [blame] | 79 | const initial = document.getElementById('user-initial'); |
| 80 | |
| 81 | circle.addEventListener('mouseenter', () => { |
| 82 | icons.forEach(icon => { |
| 83 | const tooltip = icon.nextElementSibling; |
| 84 | hideTooltip(tooltip); |
| 85 | }); |
| 86 | showTooltip(tooltipUser); |
| 87 | initial.style.color = "#7f9f7f"; |
| Davit Tabidze | 0007727 | 2024-06-11 20:19:36 +0400 | [diff] [blame] | 88 | }); |
| 89 | |
| Davit Tabidze | 9ca4926 | 2024-07-10 15:51:27 +0400 | [diff] [blame] | 90 | circle.addEventListener('mouseleave', () => { |
| 91 | hideTooltip(tooltipUser); |
| 92 | initial.style.color = "#d4888d"; |
| 93 | }); |
| Davit Tabidze | 0007727 | 2024-06-11 20:19:36 +0400 | [diff] [blame] | 94 | |
| Davit Tabidze | 9ca4926 | 2024-07-10 15:51:27 +0400 | [diff] [blame] | 95 | let hideTimeout; |
| 96 | let activeTooltip; |
| Davit Tabidze | 0007727 | 2024-06-11 20:19:36 +0400 | [diff] [blame] | 97 | |
| Davit Tabidze | 0007727 | 2024-06-11 20:19:36 +0400 | [diff] [blame] | 98 | icons.forEach(function (icon) { |
| gio | 33fa9ca | 2024-08-16 10:25:24 +0400 | [diff] [blame] | 99 | if (activeAppId && icon.getAttribute("data-app-id") === activeAppId) { |
| 100 | icon.style.color = "var(--button)"; |
| 101 | } |
| Davit Tabidze | 0007727 | 2024-06-11 20:19:36 +0400 | [diff] [blame] | 102 | icon.addEventListener("click", function (event) { |
| 103 | event.stopPropagation(); |
| 104 | const appUrl = this.getAttribute("data-app-url"); |
| 105 | const appId = this.getAttribute("data-app-id"); |
| Davit Tabidze | 9ca4926 | 2024-07-10 15:51:27 +0400 | [diff] [blame] | 106 | const modalId = this.getAttribute("data-modal-id"); |
| 107 | |
| 108 | if (!appUrl && modalId) { |
| Davit Tabidze | 0007727 | 2024-06-11 20:19:36 +0400 | [diff] [blame] | 109 | openModal(document.getElementById(modalId)); |
| 110 | } else { |
| gio | 33fa9ca | 2024-08-16 10:25:24 +0400 | [diff] [blame] | 111 | if (!iframes[appId]) { |
| 112 | createIframe(appId, appUrl); |
| 113 | } |
| 114 | activeAppId = appId; |
| Davit Tabidze | 0007727 | 2024-06-11 20:19:36 +0400 | [diff] [blame] | 115 | showIframe(appId); |
| Davit Tabidze | 9ca4926 | 2024-07-10 15:51:27 +0400 | [diff] [blame] | 116 | document.querySelectorAll(".app-icon").forEach((icon) => { |
| 117 | icon.style.color = "var(--bodyBg)"; |
| 118 | }); |
| 119 | this.style.color = "var(--button)"; |
| 120 | }; |
| Davit Tabidze | 0007727 | 2024-06-11 20:19:36 +0400 | [diff] [blame] | 121 | }); |
| Davit Tabidze | 9ca4926 | 2024-07-10 15:51:27 +0400 | [diff] [blame] | 122 | |
| 123 | const tooltip = icon.nextElementSibling; |
| Davit Tabidze | 207ce08 | 2024-04-09 19:15:25 +0400 | [diff] [blame] | 124 | [ |
| Davit Tabidze | 9ca4926 | 2024-07-10 15:51:27 +0400 | [diff] [blame] | 125 | ['mouseenter', () => { |
| 126 | clearTimeout(hideTimeout); |
| 127 | if (activeTooltip && activeTooltip !== tooltip) { |
| 128 | hideTooltip(activeTooltip); |
| 129 | }; |
| 130 | const rect = icon.getBoundingClientRect(); |
| 131 | tooltip.style.top = `${rect.top + 26}px`; |
| 132 | showTooltip(tooltip); |
| 133 | activeTooltip = tooltip; |
| 134 | }], |
| 135 | ['mouseleave', () => { |
| 136 | hideTimeout = setTimeout(() => { |
| 137 | hideTooltip(tooltip); |
| 138 | if (activeTooltip === tooltip) { |
| 139 | activeTooltip = null; |
| 140 | }; |
| 141 | }, 200); |
| 142 | }], |
| Davit Tabidze | 207ce08 | 2024-04-09 19:15:25 +0400 | [diff] [blame] | 143 | ].forEach(([event, listener]) => { |
| Davit Tabidze | 0007727 | 2024-06-11 20:19:36 +0400 | [diff] [blame] | 144 | icon.addEventListener(event, listener); |
| Davit Tabidze | 207ce08 | 2024-04-09 19:15:25 +0400 | [diff] [blame] | 145 | }); |
| Davit Tabidze | 9ca4926 | 2024-07-10 15:51:27 +0400 | [diff] [blame] | 146 | |
| 147 | tooltip.addEventListener('mouseenter', () => { |
| 148 | clearTimeout(hideTimeout); |
| 149 | }); |
| 150 | |
| 151 | tooltip.addEventListener('mouseleave', () => { |
| 152 | hideTimeout = setTimeout(() => { |
| 153 | hideTooltip(tooltip); |
| 154 | if (activeTooltip === tooltip) { |
| 155 | activeTooltip = null; |
| 156 | }; |
| 157 | }, 200); |
| 158 | }); |
| Davit Tabidze | 0007727 | 2024-06-11 20:19:36 +0400 | [diff] [blame] | 159 | }); |
| 160 | |
| gio | 92d8686 | 2024-05-21 12:51:31 +0400 | [diff] [blame] | 161 | let visibleModal = undefined; |
| Davit Tabidze | 0007727 | 2024-06-11 20:19:36 +0400 | [diff] [blame] | 162 | const openModal = function (modal) { |
| gio | 92d8686 | 2024-05-21 12:51:31 +0400 | [diff] [blame] | 163 | modal.removeAttribute("close"); |
| 164 | modal.setAttribute("open", true); |
| Davit Tabidze | 0007727 | 2024-06-11 20:19:36 +0400 | [diff] [blame] | 165 | visibleModal = modal; |
| gio | 92d8686 | 2024-05-21 12:51:31 +0400 | [diff] [blame] | 166 | }; |
| Davit Tabidze | 9ca4926 | 2024-07-10 15:51:27 +0400 | [diff] [blame] | 167 | |
| Davit Tabidze | 0007727 | 2024-06-11 20:19:36 +0400 | [diff] [blame] | 168 | const closeModal = function (modal) { |
| gio | 92d8686 | 2024-05-21 12:51:31 +0400 | [diff] [blame] | 169 | modal.removeAttribute("open"); |
| 170 | modal.setAttribute("close", true); |
| Davit Tabidze | 0007727 | 2024-06-11 20:19:36 +0400 | [diff] [blame] | 171 | visibleModal = undefined; |
| gio | 92d8686 | 2024-05-21 12:51:31 +0400 | [diff] [blame] | 172 | }; |
| Davit Tabidze | 0007727 | 2024-06-11 20:19:36 +0400 | [diff] [blame] | 173 | |
| 174 | const helpButtons = document.querySelectorAll('.help-button'); |
| Davit Tabidze | 9ca4926 | 2024-07-10 15:51:27 +0400 | [diff] [blame] | 175 | |
| Davit Tabidze | 0007727 | 2024-06-11 20:19:36 +0400 | [diff] [blame] | 176 | helpButtons.forEach(function (button) { |
| 177 | button.addEventListener('click', function (event) { |
| 178 | event.stopPropagation(); |
| 179 | const buttonId = button.getAttribute('id'); |
| 180 | const modalId = 'modal-' + buttonId.substring("help-button-".length); |
| 181 | const closeHelpId = "close-help-" + buttonId.substring("help-button-".length); |
| 182 | const modal = document.getElementById(modalId); |
| 183 | openModal(modal); |
| 184 | const closeHelpButton = document.getElementById(closeHelpId); |
| 185 | closeHelpButton.addEventListener('click', function (event) { |
| 186 | event.stopPropagation(); |
| 187 | closeModal(modal); |
| 188 | }); |
| Davit Tabidze | 207ce08 | 2024-04-09 19:15:25 +0400 | [diff] [blame] | 189 | }); |
| gio | 92d8686 | 2024-05-21 12:51:31 +0400 | [diff] [blame] | 190 | }); |
| Davit Tabidze | 0007727 | 2024-06-11 20:19:36 +0400 | [diff] [blame] | 191 | |
| 192 | const modalHelpButtons = document.querySelectorAll('.title-menu'); |
| Davit Tabidze | 9ca4926 | 2024-07-10 15:51:27 +0400 | [diff] [blame] | 193 | |
| Davit Tabidze | 0007727 | 2024-06-11 20:19:36 +0400 | [diff] [blame] | 194 | modalHelpButtons.forEach(function (button) { |
| 195 | button.addEventListener('click', function (event) { |
| 196 | event.stopPropagation(); |
| 197 | const helpTitle = button.getAttribute('id'); |
| 198 | const helpTitleId = helpTitle.substring('title-'.length); |
| 199 | const helpContentId = 'help-content-' + helpTitleId; |
| Davit Tabidze | 9ca4926 | 2024-07-10 15:51:27 +0400 | [diff] [blame] | 200 | let clDiv = document.getElementById(helpContentId).parentNode; |
| 201 | const allContentElements = clDiv.querySelectorAll('.help-content'); |
| 202 | |
| Davit Tabidze | 0007727 | 2024-06-11 20:19:36 +0400 | [diff] [blame] | 203 | allContentElements.forEach(function (contentElement) { |
| 204 | contentElement.style.display = "none"; |
| 205 | }); |
| Davit Tabidze | 9ca4926 | 2024-07-10 15:51:27 +0400 | [diff] [blame] | 206 | |
| 207 | let currentHelpTitle = button; |
| 208 | while (currentHelpTitle && !currentHelpTitle.classList.contains('modal-left')) { |
| 209 | currentHelpTitle = currentHelpTitle.parentNode; |
| 210 | if (currentHelpTitle === document.body) { |
| 211 | currentHelpTitle = null; |
| 212 | break; |
| 213 | } |
| 214 | } |
| 215 | |
| 216 | currentHelpTitle.querySelectorAll('.title-menu').forEach(function (button) { |
| Davit Tabidze | 0007727 | 2024-06-11 20:19:36 +0400 | [diff] [blame] | 217 | button.removeAttribute("aria-current"); |
| 218 | }); |
| Davit Tabidze | 9ca4926 | 2024-07-10 15:51:27 +0400 | [diff] [blame] | 219 | |
| Davit Tabidze | 0007727 | 2024-06-11 20:19:36 +0400 | [diff] [blame] | 220 | document.getElementById(helpContentId).style.display = 'block'; |
| 221 | button.setAttribute("aria-current", "page"); |
| 222 | }); |
| 223 | }); |
| 224 | |
| 225 | document.addEventListener("keydown", (event) => { |
| 226 | if (event.key === "Escape" && visibleModal) { |
| 227 | closeModal(visibleModal); |
| 228 | } |
| 229 | }); |
| 230 | |
| gio | 92d8686 | 2024-05-21 12:51:31 +0400 | [diff] [blame] | 231 | document.addEventListener("click", (event) => { |
| Davit Tabidze | 9ca4926 | 2024-07-10 15:51:27 +0400 | [diff] [blame] | 232 | if (visibleModal === null || visibleModal === undefined) return; |
| Davit Tabidze | 0007727 | 2024-06-11 20:19:36 +0400 | [diff] [blame] | 233 | const modalContent = visibleModal.querySelector("article"); |
| 234 | const closeButton = visibleModal.querySelector(".close-button"); |
| 235 | if (!modalContent.contains(event.target) || closeButton.contains(event.target)) { |
| 236 | closeModal(visibleModal); |
| 237 | } |
| gio | 92d8686 | 2024-05-21 12:51:31 +0400 | [diff] [blame] | 238 | }); |
| gio | 33fa9ca | 2024-08-16 10:25:24 +0400 | [diff] [blame] | 239 | } |
| Davit Tabidze | 9ca4926 | 2024-07-10 15:51:27 +0400 | [diff] [blame] | 240 | |
| gio | 33fa9ca | 2024-08-16 10:25:24 +0400 | [diff] [blame] | 241 | let activeAppId = undefined; |
| 242 | const iframes = {}; |
| 243 | const rightPanel = document.getElementById('right-panel'); |
| Davit Tabidze | 9ca4926 | 2024-07-10 15:51:27 +0400 | [diff] [blame] | 244 | |
| gio | 33fa9ca | 2024-08-16 10:25:24 +0400 | [diff] [blame] | 245 | function showIframe(appId) { |
| 246 | document.querySelectorAll('.appFrame').forEach(iframe => { |
| 247 | iframe.style.display = iframe.id === `appFrame-${appId}` ? 'block' : 'none'; |
| 248 | }); |
| 249 | }; |
| Davit Tabidze | 9ca4926 | 2024-07-10 15:51:27 +0400 | [diff] [blame] | 250 | |
| gio | 33fa9ca | 2024-08-16 10:25:24 +0400 | [diff] [blame] | 251 | function createIframe(appId, appUrl) { |
| 252 | const iframe = document.createElement('iframe'); |
| 253 | iframe.id = `appFrame-${appId}`; |
| 254 | iframe.className = 'appFrame'; |
| 255 | iframe.src = appUrl; |
| 256 | iframe.style.display = 'none'; |
| 257 | rightPanel.appendChild(iframe); |
| 258 | iframes[appId] = iframe; |
| Davit Tabidze | 9ca4926 | 2024-07-10 15:51:27 +0400 | [diff] [blame] | 259 | }; |