blob: be5f21665c37d7a684884050bb6e0403efccc97e [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() {
28 fetch("/").then(resp => resp.text()).then(resp => {
29 const tmp = document.createElement("div");
30 tmp.innerHTML = resp;
31 const apps = document.querySelector(".app-list");
32 let existing = [...document.querySelectorAll(".app-container")];
33 let current = [...tmp.querySelectorAll(".app-container")];
34 const getId = (e) => e.getAttribute("id");
35 const existingIds = existing.map(getId);
36 const currentIds = current.map(getId);
37 existing.forEach((e) => {
38 const id = getId(e);
39 if (!currentIds.includes(id)) {
40 e.classList.add("fadeout");
41 setTimeout(() => apps.removeChild(e), 1900);
42 }
43 });
44 let prevId = undefined;
45 current.forEach((c) => {
46 const id = getId(c);
47 if (existingIds.includes(id)) {
48 prevId = id;
49 return;
50 }
51 c.classList.add("pulsate");
52 if (prevId) {
53 apps.insertBefore(c, document.getElementById(prevId).nextSibling);
54 } else {
55 apps.insertBefore(c, apps.firstChild);
56 }
57 prevId = id;
58 });
59 initDock();
60 setTimeout(reloadDock, 5000);
61 });
62}
63
64function initDock() {
Davit Tabidze9ca49262024-07-10 15:51:27 +040065 const icons = document.querySelectorAll(".app-icon");
Davit Tabidze00077272024-06-11 20:19:36 +040066 const circle = document.querySelector(".user-circle");
67 const tooltipUser = document.querySelector("#tooltip-user");
Davit Tabidze9ca49262024-07-10 15:51:27 +040068 const initial = document.getElementById('user-initial');
69
70 circle.addEventListener('mouseenter', () => {
71 icons.forEach(icon => {
72 const tooltip = icon.nextElementSibling;
73 hideTooltip(tooltip);
74 });
75 showTooltip(tooltipUser);
76 initial.style.color = "#7f9f7f";
Davit Tabidze00077272024-06-11 20:19:36 +040077 });
78
Davit Tabidze9ca49262024-07-10 15:51:27 +040079 circle.addEventListener('mouseleave', () => {
80 hideTooltip(tooltipUser);
81 initial.style.color = "#d4888d";
82 });
Davit Tabidze00077272024-06-11 20:19:36 +040083
Davit Tabidze9ca49262024-07-10 15:51:27 +040084 let hideTimeout;
85 let activeTooltip;
Davit Tabidze00077272024-06-11 20:19:36 +040086
Davit Tabidze00077272024-06-11 20:19:36 +040087 icons.forEach(function (icon) {
gio33fa9ca2024-08-16 10:25:24 +040088 if (activeAppId && icon.getAttribute("data-app-id") === activeAppId) {
89 icon.style.color = "var(--button)";
90 }
Davit Tabidze00077272024-06-11 20:19:36 +040091 icon.addEventListener("click", function (event) {
92 event.stopPropagation();
93 const appUrl = this.getAttribute("data-app-url");
94 const appId = this.getAttribute("data-app-id");
Davit Tabidze9ca49262024-07-10 15:51:27 +040095 const modalId = this.getAttribute("data-modal-id");
96
97 if (!appUrl && modalId) {
Davit Tabidze00077272024-06-11 20:19:36 +040098 openModal(document.getElementById(modalId));
99 } else {
gio33fa9ca2024-08-16 10:25:24 +0400100 if (!iframes[appId]) {
101 createIframe(appId, appUrl);
102 }
103 activeAppId = appId;
Davit Tabidze00077272024-06-11 20:19:36 +0400104 showIframe(appId);
Davit Tabidze9ca49262024-07-10 15:51:27 +0400105 document.querySelectorAll(".app-icon").forEach((icon) => {
106 icon.style.color = "var(--bodyBg)";
107 });
108 this.style.color = "var(--button)";
109 };
Davit Tabidze00077272024-06-11 20:19:36 +0400110 });
Davit Tabidze9ca49262024-07-10 15:51:27 +0400111
112 const tooltip = icon.nextElementSibling;
Davit Tabidze207ce082024-04-09 19:15:25 +0400113 [
Davit Tabidze9ca49262024-07-10 15:51:27 +0400114 ['mouseenter', () => {
115 clearTimeout(hideTimeout);
116 if (activeTooltip && activeTooltip !== tooltip) {
117 hideTooltip(activeTooltip);
118 };
119 const rect = icon.getBoundingClientRect();
120 tooltip.style.top = `${rect.top + 26}px`;
121 showTooltip(tooltip);
122 activeTooltip = tooltip;
123 }],
124 ['mouseleave', () => {
125 hideTimeout = setTimeout(() => {
126 hideTooltip(tooltip);
127 if (activeTooltip === tooltip) {
128 activeTooltip = null;
129 };
130 }, 200);
131 }],
Davit Tabidze207ce082024-04-09 19:15:25 +0400132 ].forEach(([event, listener]) => {
Davit Tabidze00077272024-06-11 20:19:36 +0400133 icon.addEventListener(event, listener);
Davit Tabidze207ce082024-04-09 19:15:25 +0400134 });
Davit Tabidze9ca49262024-07-10 15:51:27 +0400135
136 tooltip.addEventListener('mouseenter', () => {
137 clearTimeout(hideTimeout);
138 });
139
140 tooltip.addEventListener('mouseleave', () => {
141 hideTimeout = setTimeout(() => {
142 hideTooltip(tooltip);
143 if (activeTooltip === tooltip) {
144 activeTooltip = null;
145 };
146 }, 200);
147 });
Davit Tabidze00077272024-06-11 20:19:36 +0400148 });
149
gio92d86862024-05-21 12:51:31 +0400150 let visibleModal = undefined;
Davit Tabidze00077272024-06-11 20:19:36 +0400151 const openModal = function (modal) {
gio92d86862024-05-21 12:51:31 +0400152 modal.removeAttribute("close");
153 modal.setAttribute("open", true);
Davit Tabidze00077272024-06-11 20:19:36 +0400154 visibleModal = modal;
gio92d86862024-05-21 12:51:31 +0400155 };
Davit Tabidze9ca49262024-07-10 15:51:27 +0400156
Davit Tabidze00077272024-06-11 20:19:36 +0400157 const closeModal = function (modal) {
gio92d86862024-05-21 12:51:31 +0400158 modal.removeAttribute("open");
159 modal.setAttribute("close", true);
Davit Tabidze00077272024-06-11 20:19:36 +0400160 visibleModal = undefined;
gio92d86862024-05-21 12:51:31 +0400161 };
Davit Tabidze00077272024-06-11 20:19:36 +0400162
163 const helpButtons = document.querySelectorAll('.help-button');
Davit Tabidze9ca49262024-07-10 15:51:27 +0400164
Davit Tabidze00077272024-06-11 20:19:36 +0400165 helpButtons.forEach(function (button) {
166 button.addEventListener('click', function (event) {
167 event.stopPropagation();
168 const buttonId = button.getAttribute('id');
169 const modalId = 'modal-' + buttonId.substring("help-button-".length);
170 const closeHelpId = "close-help-" + buttonId.substring("help-button-".length);
171 const modal = document.getElementById(modalId);
172 openModal(modal);
173 const closeHelpButton = document.getElementById(closeHelpId);
174 closeHelpButton.addEventListener('click', function (event) {
175 event.stopPropagation();
176 closeModal(modal);
177 });
Davit Tabidze207ce082024-04-09 19:15:25 +0400178 });
gio92d86862024-05-21 12:51:31 +0400179 });
Davit Tabidze00077272024-06-11 20:19:36 +0400180
181 const modalHelpButtons = document.querySelectorAll('.title-menu');
Davit Tabidze9ca49262024-07-10 15:51:27 +0400182
Davit Tabidze00077272024-06-11 20:19:36 +0400183 modalHelpButtons.forEach(function (button) {
184 button.addEventListener('click', function (event) {
185 event.stopPropagation();
186 const helpTitle = button.getAttribute('id');
187 const helpTitleId = helpTitle.substring('title-'.length);
188 const helpContentId = 'help-content-' + helpTitleId;
Davit Tabidze9ca49262024-07-10 15:51:27 +0400189 let clDiv = document.getElementById(helpContentId).parentNode;
190 const allContentElements = clDiv.querySelectorAll('.help-content');
191
Davit Tabidze00077272024-06-11 20:19:36 +0400192 allContentElements.forEach(function (contentElement) {
193 contentElement.style.display = "none";
194 });
Davit Tabidze9ca49262024-07-10 15:51:27 +0400195
196 let currentHelpTitle = button;
197 while (currentHelpTitle && !currentHelpTitle.classList.contains('modal-left')) {
198 currentHelpTitle = currentHelpTitle.parentNode;
199 if (currentHelpTitle === document.body) {
200 currentHelpTitle = null;
201 break;
202 }
203 }
204
205 currentHelpTitle.querySelectorAll('.title-menu').forEach(function (button) {
Davit Tabidze00077272024-06-11 20:19:36 +0400206 button.removeAttribute("aria-current");
207 });
Davit Tabidze9ca49262024-07-10 15:51:27 +0400208
Davit Tabidze00077272024-06-11 20:19:36 +0400209 document.getElementById(helpContentId).style.display = 'block';
210 button.setAttribute("aria-current", "page");
211 });
212 });
213
214 document.addEventListener("keydown", (event) => {
215 if (event.key === "Escape" && visibleModal) {
216 closeModal(visibleModal);
217 }
218 });
219
gio92d86862024-05-21 12:51:31 +0400220 document.addEventListener("click", (event) => {
Davit Tabidze9ca49262024-07-10 15:51:27 +0400221 if (visibleModal === null || visibleModal === undefined) return;
Davit Tabidze00077272024-06-11 20:19:36 +0400222 const modalContent = visibleModal.querySelector("article");
223 const closeButton = visibleModal.querySelector(".close-button");
224 if (!modalContent.contains(event.target) || closeButton.contains(event.target)) {
225 closeModal(visibleModal);
226 }
gio92d86862024-05-21 12:51:31 +0400227 });
gio33fa9ca2024-08-16 10:25:24 +0400228}
Davit Tabidze9ca49262024-07-10 15:51:27 +0400229
gio33fa9ca2024-08-16 10:25:24 +0400230let activeAppId = undefined;
231const iframes = {};
232const rightPanel = document.getElementById('right-panel');
Davit Tabidze9ca49262024-07-10 15:51:27 +0400233
gio33fa9ca2024-08-16 10:25:24 +0400234function showIframe(appId) {
235 document.querySelectorAll('.appFrame').forEach(iframe => {
236 iframe.style.display = iframe.id === `appFrame-${appId}` ? 'block' : 'none';
237 });
238};
Davit Tabidze9ca49262024-07-10 15:51:27 +0400239
gio33fa9ca2024-08-16 10:25:24 +0400240function createIframe(appId, appUrl) {
241 const iframe = document.createElement('iframe');
242 iframe.id = `appFrame-${appId}`;
243 iframe.className = 'appFrame';
244 iframe.src = appUrl;
245 iframe.style.display = 'none';
246 rightPanel.appendChild(iframe);
247 iframes[appId] = iframe;
Davit Tabidze9ca49262024-07-10 15:51:27 +0400248};