blob: ab34e4ce76b3aa86ff181bf0fe0ec5906e2bd826 [file] [log] [blame]
Davit Tabidze9ca49262024-07-10 15:51:27 +04001function showTooltip(obj) {
2 obj.style.visibility = 'visible';
3 obj.style.opacity = '1';
4}
5function hideTooltip(obj) {
6 obj.style.visibility = 'hidden';
7 obj.style.opacity = '0';
8}
9
Davit Tabidze207ce082024-04-09 19:15:25 +040010document.addEventListener("DOMContentLoaded", function () {
Davit Tabidze00077272024-06-11 20:19:36 +040011 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 Tabidze9ca49262024-07-10 15:51:27 +040012 document.getElementById('appFrame-default').style.backgroundColor = '#d6d6d6';
gio33fa9ca2024-08-16 10:25:24 +040013 initDock();
14 setTimeout(reloadDock, 5000);
15});
16
17function 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
27function reloadDock() {
gio1bf00802024-08-17 12:31:41 +040028 fetch("/")
29 .then((resp) => {
30 if (resp.ok) {
31 return resp.text();
32 } else {
33 return undefined;
gio33fa9ca2024-08-16 10:25:24 +040034 }
gio1bf00802024-08-17 12:31:41 +040035 })
36 .then((resp) => {
37 if (!resp) {
gio33fa9ca2024-08-16 10:25:24 +040038 return;
39 }
gio1bf00802024-08-17 12:31:41 +040040 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));
gio33fa9ca2024-08-16 10:25:24 +040073}
74
75function initDock() {
Davit Tabidze9ca49262024-07-10 15:51:27 +040076 const icons = document.querySelectorAll(".app-icon");
Davit Tabidze00077272024-06-11 20:19:36 +040077 const circle = document.querySelector(".user-circle");
78 const tooltipUser = document.querySelector("#tooltip-user");
Davit Tabidze9ca49262024-07-10 15:51:27 +040079 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 Tabidze00077272024-06-11 20:19:36 +040088 });
89
Davit Tabidze9ca49262024-07-10 15:51:27 +040090 circle.addEventListener('mouseleave', () => {
91 hideTooltip(tooltipUser);
92 initial.style.color = "#d4888d";
93 });
Davit Tabidze00077272024-06-11 20:19:36 +040094
Davit Tabidze9ca49262024-07-10 15:51:27 +040095 let hideTimeout;
96 let activeTooltip;
Davit Tabidze00077272024-06-11 20:19:36 +040097
Davit Tabidze00077272024-06-11 20:19:36 +040098 icons.forEach(function (icon) {
gio33fa9ca2024-08-16 10:25:24 +040099 if (activeAppId && icon.getAttribute("data-app-id") === activeAppId) {
100 icon.style.color = "var(--button)";
101 }
Davit Tabidze00077272024-06-11 20:19:36 +0400102 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 Tabidze9ca49262024-07-10 15:51:27 +0400106 const modalId = this.getAttribute("data-modal-id");
107
108 if (!appUrl && modalId) {
Davit Tabidze00077272024-06-11 20:19:36 +0400109 openModal(document.getElementById(modalId));
110 } else {
gio33fa9ca2024-08-16 10:25:24 +0400111 if (!iframes[appId]) {
112 createIframe(appId, appUrl);
113 }
114 activeAppId = appId;
Davit Tabidze00077272024-06-11 20:19:36 +0400115 showIframe(appId);
Davit Tabidze9ca49262024-07-10 15:51:27 +0400116 document.querySelectorAll(".app-icon").forEach((icon) => {
117 icon.style.color = "var(--bodyBg)";
118 });
119 this.style.color = "var(--button)";
120 };
Davit Tabidze00077272024-06-11 20:19:36 +0400121 });
Davit Tabidze9ca49262024-07-10 15:51:27 +0400122
123 const tooltip = icon.nextElementSibling;
Davit Tabidze207ce082024-04-09 19:15:25 +0400124 [
Davit Tabidze9ca49262024-07-10 15:51:27 +0400125 ['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 Tabidze207ce082024-04-09 19:15:25 +0400143 ].forEach(([event, listener]) => {
Davit Tabidze00077272024-06-11 20:19:36 +0400144 icon.addEventListener(event, listener);
Davit Tabidze207ce082024-04-09 19:15:25 +0400145 });
Davit Tabidze9ca49262024-07-10 15:51:27 +0400146
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 Tabidze00077272024-06-11 20:19:36 +0400159 });
160
gio92d86862024-05-21 12:51:31 +0400161 let visibleModal = undefined;
Davit Tabidze00077272024-06-11 20:19:36 +0400162 const openModal = function (modal) {
gio92d86862024-05-21 12:51:31 +0400163 modal.removeAttribute("close");
164 modal.setAttribute("open", true);
Davit Tabidze00077272024-06-11 20:19:36 +0400165 visibleModal = modal;
gio92d86862024-05-21 12:51:31 +0400166 };
Davit Tabidze9ca49262024-07-10 15:51:27 +0400167
Davit Tabidze00077272024-06-11 20:19:36 +0400168 const closeModal = function (modal) {
gio92d86862024-05-21 12:51:31 +0400169 modal.removeAttribute("open");
170 modal.setAttribute("close", true);
Davit Tabidze00077272024-06-11 20:19:36 +0400171 visibleModal = undefined;
gio92d86862024-05-21 12:51:31 +0400172 };
Davit Tabidze00077272024-06-11 20:19:36 +0400173
174 const helpButtons = document.querySelectorAll('.help-button');
Davit Tabidze9ca49262024-07-10 15:51:27 +0400175
Davit Tabidze00077272024-06-11 20:19:36 +0400176 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 Tabidze207ce082024-04-09 19:15:25 +0400189 });
gio92d86862024-05-21 12:51:31 +0400190 });
Davit Tabidze00077272024-06-11 20:19:36 +0400191
192 const modalHelpButtons = document.querySelectorAll('.title-menu');
Davit Tabidze9ca49262024-07-10 15:51:27 +0400193
Davit Tabidze00077272024-06-11 20:19:36 +0400194 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 Tabidze9ca49262024-07-10 15:51:27 +0400200 let clDiv = document.getElementById(helpContentId).parentNode;
201 const allContentElements = clDiv.querySelectorAll('.help-content');
202
Davit Tabidze00077272024-06-11 20:19:36 +0400203 allContentElements.forEach(function (contentElement) {
204 contentElement.style.display = "none";
205 });
Davit Tabidze9ca49262024-07-10 15:51:27 +0400206
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 Tabidze00077272024-06-11 20:19:36 +0400217 button.removeAttribute("aria-current");
218 });
Davit Tabidze9ca49262024-07-10 15:51:27 +0400219
Davit Tabidze00077272024-06-11 20:19:36 +0400220 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
gio92d86862024-05-21 12:51:31 +0400231 document.addEventListener("click", (event) => {
Davit Tabidze9ca49262024-07-10 15:51:27 +0400232 if (visibleModal === null || visibleModal === undefined) return;
Davit Tabidze00077272024-06-11 20:19:36 +0400233 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 }
gio92d86862024-05-21 12:51:31 +0400238 });
gio33fa9ca2024-08-16 10:25:24 +0400239}
Davit Tabidze9ca49262024-07-10 15:51:27 +0400240
gio33fa9ca2024-08-16 10:25:24 +0400241let activeAppId = undefined;
242const iframes = {};
243const rightPanel = document.getElementById('right-panel');
Davit Tabidze9ca49262024-07-10 15:51:27 +0400244
gio33fa9ca2024-08-16 10:25:24 +0400245function showIframe(appId) {
246 document.querySelectorAll('.appFrame').forEach(iframe => {
247 iframe.style.display = iframe.id === `appFrame-${appId}` ? 'block' : 'none';
248 });
249};
Davit Tabidze9ca49262024-07-10 15:51:27 +0400250
gio33fa9ca2024-08-16 10:25:24 +0400251function 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 Tabidze9ca49262024-07-10 15:51:27 +0400259};