summaryrefslogtreecommitdiffstats
path: root/web/gui/ilove.html
diff options
context:
space:
mode:
Diffstat (limited to 'web/gui/ilove.html')
-rw-r--r--web/gui/ilove.html302
1 files changed, 302 insertions, 0 deletions
diff --git a/web/gui/ilove.html b/web/gui/ilove.html
new file mode 100644
index 000000000..f82b1cfd3
--- /dev/null
+++ b/web/gui/ilove.html
@@ -0,0 +1,302 @@
+<!DOCTYPE html>
+<!-- SPDX-License-Identifier: GPL-3.0-or-later -->
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>I Love SVG</title>
+ <style>
+ * {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+ }
+
+ body {
+ background-color: gray;
+ font-family: 'Arial', sans-serif;
+ display: flex;
+ flex-direction: column;
+ height: 100vh;
+ padding: 20px;
+ }
+
+ .svg-container {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 10px;
+ margin-bottom: 20px;
+ }
+
+ .svg-container img {
+ height: 75px;
+ cursor: pointer;
+ }
+
+ .input-wrapper {
+ display: flex;
+ align-items: center;
+ justify-content: center; /* Centers the items horizontally */
+ flex-wrap: wrap; /* Allow the items to wrap if there isn't enough horizontal space */
+ gap: 10px; /* Gap between the items */
+ }
+
+ .input-wrapper #labelInput {
+ font-family: 'IBM Plex Sans', sans-serif;
+ font-weight: bold;
+ font-size: 24px;
+ color: white;
+ background-color: gray;
+ border: none;
+ cursor: default;
+ padding: 10px 15px;
+ margin-right: 10px;
+ text-align: right;
+ width: 135px;
+ }
+
+ .string-input input {
+ font-family: 'IBM Plex Sans', sans-serif;
+ font-weight: bold;
+ font-size: 24px;
+ background-color: black;
+ color: white;
+ border: none;
+ border-radius: 8px;
+ padding: 10px 15px;
+ width: 100%;
+ box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.2);
+ outline: none;
+ }
+
+ .string-input input:focus {
+ box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.3);
+ }
+
+ .big-svg-container {
+ flex: 1;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ overflow: hidden;
+ }
+
+ .big-svg {
+ max-width: 100%;
+ max-height: 95%;
+ object-fit: contain;
+ }
+
+ .input-wrapper button {
+ background-color: darkgray;
+ color: white;
+ border: none;
+ border-radius: 8px;
+ padding: 5px 10px;
+ margin-left: 10px; /* Space between buttons */
+ cursor: pointer;
+ transition: background-color 0.3s; /* Smooth transition for hover effect */
+ }
+
+ .input-wrapper button:hover {
+ background-color: #555; /* Darker shade on hover */
+ }
+
+ /* Style for the dropdown */
+ #resolutionSelect {
+ background-color: darkgray; /* Same as button background */
+ color: white; /* Text color */
+ border: none; /* Remove border */
+ border-radius: 8px; /* Rounded corners, same as buttons */
+ padding: 5px 10px; /* Some padding for aesthetics */
+ margin-left: 10px; /* Space between dropdown and adjacent elements */
+ font-family: "IBM Plex Sans", sans-serif; /* Font from SVG */
+ font-weight: bold; /* Bold font */
+ font-size: 16px; /* Font size consistent with text box */
+ cursor: pointer; /* Hand cursor for better UX */
+ appearance: none; /* Remove default styling on some browsers */
+ -webkit-appearance: none; /* Remove default styling on WebKit browsers */
+ -moz-appearance: none; /* Remove default styling on Firefox */
+
+ padding: 10px 20px; /* Increase padding for more height */
+ line-height: 1.5; /* Increase line height for a taller dropdown */
+
+ /* Arrow for the dropdown */
+ 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;
+ padding-right: 40px; /* Add padding to prevent text from overlapping the arrow */
+ }
+
+ /* Hover effect for the dropdown, similar to buttons */
+ #resolutionSelect:hover {
+ background-color: #555; /* Darker shade on hover */
+ }
+
+ /* Arrow for the dropdown (this is a bit of a hack, but it works for adding a custom arrow) */
+ #resolutionSelect::-ms-expand {
+ display: none; /* Hide default arrow for IE/Edge */
+ }
+ #resolutionSelect::after {
+ content: '\25BC'; /* Down arrow symbol */
+ position: absolute;
+ top: 50%;
+ right: 10px;
+ transform: translateY(-50%);
+ pointer-events: none; /* Ensure dropdown still works when clicking arrow */
+ }
+ </style>
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
+</head>
+<body>
+<div class="svg-container">
+ <!-- SVG examples will be loaded here -->
+</div>
+
+<div class="input-wrapper">
+ <input type="text" value="You Love" id="labelInput" readonly>
+ <div class="string-input">
+ <input type="text" id="stringInput" placeholder="Enter your STRING here">
+ </div>
+ <select id="resolutionSelect">
+ <option value="360">360p</option>
+ <option value="720">720p</option>
+ <option value="1080">1080p</option>
+ <option value="4k">4k</option>
+ <option value="8k">8k</option>
+ </select>
+ <button id="copyUrl"><i class="fas fa-copy"></i><br/>URL</button>
+ <button id="downloadSvg"><i class="fas fa-download"></i><br/>SVG</button>
+ <button id="downloadPng"><i class="fas fa-image"></i><br/>PNG</button>
+ <button id="downloadWebp"><i class="fas fa-file-image"></i><br/>WEBP</button>
+</div>
+
+<div class="big-svg-container">
+ <img src="" alt="Big SVG Image" id="bigSvg" class="big-svg">
+</div>
+
+<script>
+ document.addEventListener('DOMContentLoaded', function() {
+ 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"];
+ const svgContainer = document.querySelector('.svg-container');
+ const bigSvg = document.getElementById('bigSvg');
+ const stringInput = document.getElementById('stringInput');
+
+ // Calculate the API endpoint
+ const currentUrl = new URL(window.location.href);
+ const apiEndpoint = `${currentUrl.origin}${currentUrl.pathname.replace('ilove.html', '')}api/v2/ilove.svg?love=`;
+
+ // Load examples
+ examples.forEach(example => {
+ const img = document.createElement('img');
+ img.src = `${apiEndpoint}${example}`;
+ img.addEventListener('click', function() {
+ stringInput.value = example;
+ updateBigSvg();
+ });
+ svgContainer.appendChild(img);
+ });
+
+ // Set the default value of the text box to the first word from the examples
+ stringInput.value = examples[0];
+ updateBigSvg();
+
+ // Update the big SVG when the input changes
+ stringInput.addEventListener('input', updateBigSvg);
+
+ function updateBigSvg() {
+ const encodedValue = encodeURIComponent(stringInput.value);
+ bigSvg.src = `${apiEndpoint}${encodedValue}`;
+ }
+
+ // Copy URL functionality
+ document.getElementById('copyUrl').addEventListener('click', function() {
+ const tempTextArea = document.createElement('textarea');
+ tempTextArea.value = bigSvg.src;
+ document.body.appendChild(tempTextArea);
+ tempTextArea.select();
+ document.execCommand('copy');
+ document.body.removeChild(tempTextArea);
+
+ // Update button icon and text temporarily
+ const btn = this; // 'this' refers to the clicked element (in this case, the 'copyUrl' button)
+ const originalIcon = btn.querySelector('i');
+ const breakElement = btn.querySelector('br');
+
+ // Replace the icon and text
+ originalIcon.className = "fas fa-check"; // Change to checkmark icon
+ btn.textContent = ''; // Clear the button text
+ btn.appendChild(originalIcon); // Add the checkmark icon
+ btn.appendChild(breakElement); // Add the break element
+ btn.appendChild(document.createTextNode('Copied')); // Add the "Copied" text
+
+ setTimeout(() => {
+ originalIcon.className = "fas fa-copy"; // Revert back to copy icon
+ btn.textContent = ''; // Clear the button text
+ btn.appendChild(originalIcon); // Add the copy icon
+ btn.appendChild(breakElement); // Add the break element
+ btn.appendChild(document.createTextNode('URL')); // Add the "URL" text
+ }, 2000); // Revert back after 2 seconds
+ });
+
+ // Download SVG
+ document.getElementById('downloadSvg').addEventListener('click', function() {
+ const filename = `I love ${stringInput.value}.svg`;
+ triggerDownload(bigSvg.src, filename);
+ });
+
+ // Download PNG
+ document.getElementById('downloadPng').addEventListener('click', function() {
+ convertSvgToImage('png');
+ });
+
+ // Download WEBP
+ document.getElementById('downloadWebp').addEventListener('click', function() {
+ convertSvgToImage('webp');
+ });
+
+ function convertSvgToImage(format) {
+ const image = new Image();
+ image.src = bigSvg.src;
+ image.onload = function() {
+ const resolution = getResolutionDimensions();
+
+ // Calculate the scaling factor based on the resolution width
+ const scaleFactor = resolution.width / image.width;
+
+ // Set canvas dimensions based on SVG's aspect ratio
+ const canvas = document.createElement('canvas');
+ canvas.width = image.width * scaleFactor;
+ canvas.height = image.height * scaleFactor;
+
+ const ctx = canvas.getContext('2d');
+ ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
+
+ const filename = `I love ${stringInput.value}.${format}`;
+ triggerDownload(canvas.toDataURL(`image/${format}`), filename);
+ };
+ }
+
+ function getResolutionDimensions() {
+ const resolution = document.getElementById('resolutionSelect').value;
+ switch(resolution) {
+ case "360": return { width: 640, height: 360 };
+ case "720": return { width: 1280, height: 720 };
+ case "1080": return { width: 1920, height: 1080 };
+ case "4k": return { width: 3840, height: 2160 };
+ case "8k": return { width: 7680, height: 4320 };
+ default: return { width: 640, height: 360 }; // Default to 360p
+ }
+ }
+
+ function triggerDownload(url, filename) {
+ const downloadLink = document.createElement('a');
+ downloadLink.href = url;
+ downloadLink.download = filename;
+ document.body.appendChild(downloadLink);
+ downloadLink.click();
+ document.body.removeChild(downloadLink);
+ }
+
+ });
+</script>
+</body>
+</html>