@cryptotaxi247 / netdata-1 / commits / 13a04de91

added ilove.html (#15836)

Costa Tsaousis committed Aug 17, 2023 at 23:48 UTC 13a04de917d152430a75b0ec960816e8ba923f0f
2 files changed +303
web/gui/Makefile.am
+1
@@ -62,6 +62,7 @@ dist_web_DATA = \
62 $(srcdir)/registry-alert-redirect.html \
63 $(srcdir)/registry-hello.html \
64 $(srcdir)/switch.html \
65 + $(srcdir)/ilove.html \
66 version.txt \
67 $(NULL)
68
web/gui/ilove.html new
+302
@@ -0,0 +1,302 @@
1 +<!DOCTYPE html>
2 +<!-- SPDX-License-Identifier: GPL-3.0-or-later -->
3 +<html lang="en">
4 +<head>
5 + <meta charset="UTF-8">
6 + <meta name="viewport" content="width=device-width, initial-scale=1.0">
7 + <title>I Love SVG</title>
8 + <style>
9 + * {
10 + margin: 0;
11 + padding: 0;
12 + box-sizing: border-box;
13 + }
14 +
15 + body {
16 + background-color: gray;
17 + font-family: 'Arial', sans-serif;
18 + display: flex;
19 + flex-direction: column;
20 + height: 100vh;
21 + padding: 20px;
22 + }
23 +
24 + .svg-container {
25 + display: flex;
26 + flex-wrap: wrap;
27 + gap: 10px;
28 + margin-bottom: 20px;
29 + }
30 +
31 + .svg-container img {
32 + height: 75px;
33 + cursor: pointer;
34 + }
35 +
36 + .input-wrapper {
37 + display: flex;
38 + align-items: center;
39 + justify-content: center; /* Centers the items horizontally */
40 + flex-wrap: wrap; /* Allow the items to wrap if there isn't enough horizontal space */
41 + gap: 10px; /* Gap between the items */
42 + }
43 +
44 + .input-wrapper #labelInput {
45 + font-family: 'IBM Plex Sans', sans-serif;
46 + font-weight: bold;
47 + font-size: 24px;
48 + color: white;
49 + background-color: gray;
50 + border: none;
51 + cursor: default;
52 + padding: 10px 15px;
53 + margin-right: 10px;
54 + text-align: right;
55 + width: 135px;
56 + }
57 +
58 + .string-input input {
59 + font-family: 'IBM Plex Sans', sans-serif;
60 + font-weight: bold;
61 + font-size: 24px;
62 + background-color: black;
63 + color: white;
64 + border: none;
65 + border-radius: 8px;
66 + padding: 10px 15px;
67 + width: 100%;
68 + box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.2);
69 + outline: none;
70 + }
71 +
72 + .string-input input:focus {
73 + box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.3);
74 + }
75 +
76 + .big-svg-container {
77 + flex: 1;
78 + display: flex;
79 + align-items: center;
80 + justify-content: center;
81 + overflow: hidden;
82 + }
83 +
84 + .big-svg {
85 + max-width: 100%;
86 + max-height: 95%;
87 + object-fit: contain;
88 + }
89 +
90 + .input-wrapper button {
91 + background-color: darkgray;
92 + color: white;
93 + border: none;
94 + border-radius: 8px;
95 + padding: 5px 10px;
96 + margin-left: 10px; /* Space between buttons */
97 + cursor: pointer;
98 + transition: background-color 0.3s; /* Smooth transition for hover effect */
99 + }
100 +
101 + .input-wrapper button:hover {
102 + background-color: #555; /* Darker shade on hover */
103 + }
104 +
105 + /* Style for the dropdown */
106 + #resolutionSelect {
107 + background-color: darkgray; /* Same as button background */
108 + color: white; /* Text color */
109 + border: none; /* Remove border */
110 + border-radius: 8px; /* Rounded corners, same as buttons */
111 + padding: 5px 10px; /* Some padding for aesthetics */
112 + margin-left: 10px; /* Space between dropdown and adjacent elements */
113 + font-family: "IBM Plex Sans", sans-serif; /* Font from SVG */
114 + font-weight: bold; /* Bold font */
115 + font-size: 16px; /* Font size consistent with text box */
116 + cursor: pointer; /* Hand cursor for better UX */
117 + appearance: none; /* Remove default styling on some browsers */
118 + -webkit-appearance: none; /* Remove default styling on WebKit browsers */
119 + -moz-appearance: none; /* Remove default styling on Firefox */
120 +
121 + padding: 10px 20px; /* Increase padding for more height */
122 + line-height: 1.5; /* Increase line height for a taller dropdown */
123 +
124 + /* Arrow for the dropdown */
125 + background: darkgray url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path d="M31.3 192l121.5 121.5c4.7 4.7 12.3 4.7 17 0L291.3 192c4.7-4.7 4.7-12.3 0-17l-22.6-22.6c-4.7-4.7-12.3-4.7-17 0L160 273.9 68.3 152c-4.7-4.7-12.3-4.7-17 0L28.7 174.5c-4.7 4.7-4.7 12.3 0 17.1z" fill="white"/></svg>') no-repeat right 10px center;
126 + padding-right: 40px; /* Add padding to prevent text from overlapping the arrow */
127 + }
128 +
129 + /* Hover effect for the dropdown, similar to buttons */
130 + #resolutionSelect:hover {
131 + background-color: #555; /* Darker shade on hover */
132 + }
133 +
134 + /* Arrow for the dropdown (this is a bit of a hack, but it works for adding a custom arrow) */
135 + #resolutionSelect::-ms-expand {
136 + display: none; /* Hide default arrow for IE/Edge */
137 + }
138 + #resolutionSelect::after {
139 + content: '\25BC'; /* Down arrow symbol */
140 + position: absolute;
141 + top: 50%;
142 + right: 10px;
143 + transform: translateY(-50%);
144 + pointer-events: none; /* Ensure dropdown still works when clicking arrow */
145 + }
146 + </style>
147 + <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
148 +</head>
149 +<body>
150 +<div class="svg-container">
151 + <!-- SVG examples will be loaded here -->
152 +</div>
153 +
154 +<div class="input-wrapper">
155 + <input type="text" value="You Love" id="labelInput" readonly>
156 + <div class="string-input">
157 + <input type="text" id="stringInput" placeholder="Enter your STRING here">
158 + </div>
159 + <select id="resolutionSelect">
160 + <option value="360">360p</option>
161 + <option value="720">720p</option>
162 + <option value="1080">1080p</option>
163 + <option value="4k">4k</option>
164 + <option value="8k">8k</option>
165 + </select>
166 + <button id="copyUrl"><i class="fas fa-copy"></i><br/>URL</button>
167 + <button id="downloadSvg"><i class="fas fa-download"></i><br/>SVG</button>
168 + <button id="downloadPng"><i class="fas fa-image"></i><br/>PNG</button>
169 + <button id="downloadWebp"><i class="fas fa-file-image"></i><br/>WEBP</button>
170 +</div>
171 +
172 +<div class="big-svg-container">
173 + <img src="" alt="Big SVG Image" id="bigSvg" class="big-svg">
174 +</div>
175 +
176 +<script>
177 + document.addEventListener('DOMContentLoaded', function() {
178 + const examples = ["TROUBLE", "3AM", "BUGS", "ML", "AI", "CODE", "DEV", "DevOps", "Observability", "Telemetry", "Dashboards", "Automation", "K8s", "Docker", "PostgreSQL", "NightShifts", "OnCall", "Linux", "Debian", "Ubuntu", "Arch", "Manjaro", "CentOS", "AWS"];
179 + const svgContainer = document.querySelector('.svg-container');
180 + const bigSvg = document.getElementById('bigSvg');
181 + const stringInput = document.getElementById('stringInput');
182 +
183 + // Calculate the API endpoint
184 + const currentUrl = new URL(window.location.href);
185 + const apiEndpoint = `${currentUrl.origin}${currentUrl.pathname.replace('ilove.html', '')}api/v2/ilove.svg?love=`;
186 +
187 + // Load examples
188 + examples.forEach(example => {
189 + const img = document.createElement('img');
190 + img.src = `${apiEndpoint}${example}`;
191 + img.addEventListener('click', function() {
192 + stringInput.value = example;
193 + updateBigSvg();
194 + });
195 + svgContainer.appendChild(img);
196 + });
197 +
198 + // Set the default value of the text box to the first word from the examples
199 + stringInput.value = examples[0];
200 + updateBigSvg();
201 +
202 + // Update the big SVG when the input changes
203 + stringInput.addEventListener('input', updateBigSvg);
204 +
205 + function updateBigSvg() {
206 + const encodedValue = encodeURIComponent(stringInput.value);
207 + bigSvg.src = `${apiEndpoint}${encodedValue}`;
208 + }
209 +
210 + // Copy URL functionality
211 + document.getElementById('copyUrl').addEventListener('click', function() {
212 + const tempTextArea = document.createElement('textarea');
213 + tempTextArea.value = bigSvg.src;
214 + document.body.appendChild(tempTextArea);
215 + tempTextArea.select();
216 + document.execCommand('copy');
217 + document.body.removeChild(tempTextArea);
218 +
219 + // Update button icon and text temporarily
220 + const btn = this; // 'this' refers to the clicked element (in this case, the 'copyUrl' button)
221 + const originalIcon = btn.querySelector('i');
222 + const breakElement = btn.querySelector('br');
223 +
224 + // Replace the icon and text
225 + originalIcon.className = "fas fa-check"; // Change to checkmark icon
226 + btn.textContent = ''; // Clear the button text
227 + btn.appendChild(originalIcon); // Add the checkmark icon
228 + btn.appendChild(breakElement); // Add the break element
229 + btn.appendChild(document.createTextNode('Copied')); // Add the "Copied" text
230 +
231 + setTimeout(() => {
232 + originalIcon.className = "fas fa-copy"; // Revert back to copy icon
233 + btn.textContent = ''; // Clear the button text
234 + btn.appendChild(originalIcon); // Add the copy icon
235 + btn.appendChild(breakElement); // Add the break element
236 + btn.appendChild(document.createTextNode('URL')); // Add the "URL" text
237 + }, 2000); // Revert back after 2 seconds
238 + });
239 +
240 + // Download SVG
241 + document.getElementById('downloadSvg').addEventListener('click', function() {
242 + const filename = `I love ${stringInput.value}.svg`;
243 + triggerDownload(bigSvg.src, filename);
244 + });
245 +
246 + // Download PNG
247 + document.getElementById('downloadPng').addEventListener('click', function() {
248 + convertSvgToImage('png');
249 + });
250 +
251 + // Download WEBP
252 + document.getElementById('downloadWebp').addEventListener('click', function() {
253 + convertSvgToImage('webp');
254 + });
255 +
256 + function convertSvgToImage(format) {
257 + const image = new Image();
258 + image.src = bigSvg.src;
259 + image.onload = function() {
260 + const resolution = getResolutionDimensions();
261 +
262 + // Calculate the scaling factor based on the resolution width
263 + const scaleFactor = resolution.width / image.width;
264 +
265 + // Set canvas dimensions based on SVG's aspect ratio
266 + const canvas = document.createElement('canvas');
267 + canvas.width = image.width * scaleFactor;
268 + canvas.height = image.height * scaleFactor;
269 +
270 + const ctx = canvas.getContext('2d');
271 + ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
272 +
273 + const filename = `I love ${stringInput.value}.${format}`;
274 + triggerDownload(canvas.toDataURL(`image/${format}`), filename);
275 + };
276 + }
277 +
278 + function getResolutionDimensions() {
279 + const resolution = document.getElementById('resolutionSelect').value;
280 + switch(resolution) {
281 + case "360": return { width: 640, height: 360 };
282 + case "720": return { width: 1280, height: 720 };
283 + case "1080": return { width: 1920, height: 1080 };
284 + case "4k": return { width: 3840, height: 2160 };
285 + case "8k": return { width: 7680, height: 4320 };
286 + default: return { width: 640, height: 360 }; // Default to 360p
287 + }
288 + }
289 +
290 + function triggerDownload(url, filename) {
291 + const downloadLink = document.createElement('a');
292 + downloadLink.href = url;
293 + downloadLink.download = filename;
294 + document.body.appendChild(downloadLink);
295 + downloadLink.click();
296 + document.body.removeChild(downloadLink);
297 + }
298 +
299 + });
300 +</script>
301 +</body>
302 +</html>