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>