diff --git a/Dockerfile b/Dockerfile index 49e22ea..a300b20 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,6 +5,7 @@ WORKDIR /app COPY go.mod go.sum* ./ RUN go mod download COPY *.go ./ +COPY . . RUN CGO_ENABLED=0 GOOS=linux go build -o main . # Etap minifikacji diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..7201b98 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,20 @@ +version: '3.8' + +services: + app: + container_name: ${PROJECT_NAME:-fast-links} + build: + context: . + dockerfile: Dockerfile + ports: + - "${PORT:-8080}:8080" + volumes: + - app-data:/data + environment: + - PORT=8080 + - DATA_FILE_PATH=/data/data.db + restart: unless-stopped + +# Definiujemy wolumen Docker +volumes: + app-data: diff --git a/main.go b/main.go index 2ff596c..219d117 100644 --- a/main.go +++ b/main.go @@ -8,24 +8,17 @@ import ( "log" "mkedziora/fast-links/kvstore" "net/http" + "os" "strconv" "time" ) -// var ( -// dataMap map[string]DataEntry -// mu sync.Mutex -// ) - -// func init() { -// dataMap = make(map[string]DataEntry) -// } - var store *kvstore.KVStore func init() { var err error - store, err = kvstore.NewKVStore("data.db") + filePath := os.Getenv("DATA_FILE_PATH") + store, err = kvstore.NewKVStore(filePath) if err != nil { log.Fatalf("Failed to create KVStore: %v", err) } diff --git a/public/app.html b/public/app.html index 8e053a0..bec8feb 100644 --- a/public/app.html +++ b/public/app.html @@ -13,7 +13,18 @@

Click the button to start.

+
+ + +
+
+ + +
+ +
This is a toast message!
+ diff --git a/public/css/app.css b/public/css/app.css index 10e4658..1589900 100644 --- a/public/css/app.css +++ b/public/css/app.css @@ -23,6 +23,52 @@ body { color: var(--text-color); } +.checkbox-container { + display: flex; + align-items: center; + gap: 0.5rem; + justify-content: center; +} + +.checkbox-container input[type="checkbox"] { + width: 20px; + height: 20px; + cursor: pointer; + accent-color: var(--primary-color); /* Umożliwia zmianę koloru checkboxa */ +} + +.checkbox-container label { + color: var(--text-color); + font-size: 0.9rem; + cursor: pointer; + transition: color 0.3s ease; +} + +.checkbox-container label:hover { + color: var(--primary-color); +} + +.toast { + position: fixed; + top: 20px; + left: 50%; + transform: translateX(-50%); + background-color: var(--primary-color); + color: white; + padding: 1rem 1.5rem; + border-radius: 8px; + box-shadow: 0 4px 15px var(--shadow-color); + opacity: 0; + visibility: hidden; + transition: opacity 0.5s ease, visibility 0.5s ease; + z-index: 1000; /* Umożliwia wyświetlanie toastu nad innymi elementami */ +} + +.toast.show { + opacity: 1; + visibility: visible; +} + .container { max-width: 600px; width: 100%; diff --git a/public/js/app.js b/public/js/app.js index 6120209..eb455e2 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -1,18 +1,55 @@ let lastData = ""; const urlParams = new URLSearchParams(window.location.search); const id = urlParams.get("id"); -let new_url = ""; let fetchingData; let newWindow; -document.getElementById("startBtn").addEventListener("click", function () { - document.getElementById("info").textContent = "Waiting for a new address..."; - newWindow = window.open("about:blank", "_blank", ""); +let listening = false; +const startBtn = document.getElementById("startBtn"); +const autoListen = document.getElementById("autoListen"); +const saveOldLink = document.getElementById("saveOldLink"); +const info = document.getElementById("info"); +const toast = document.getElementById("toast"); + +autoListen.addEventListener("click", function () { + if (autoListen.checked) { + saveOldLink.checked = true; + toast.textContent = "Attention! You must allow pop-ups to use this feature!"; + toast.classList.add("show"); + setTimeout(() => { + toast.classList.remove("show"); + }, 3000); + } +}); + +saveOldLink.addEventListener("click", function () { + if (autoListen.checked && !this.checked) autoListen.checked = false; +}); + +startBtn.addEventListener("click", function () { + info.textContent = "Waiting for a new address..."; + listening = !listening; + if (listening) startBtn.textContent = "Stop listening"; + else { + startBtn.textContent = "Start listening"; + clearInterval(fetchingData); + return; + } + + if (!saveOldLink.checked) { + lastData = ""; + const a = document.getElementById("url"); + a.href = ""; + a.textContent = ""; + } + openNewTab(); fetchingData = setInterval(checkForNewAddress, 1000); }); -function checkForNewAddress() { - // Dodanie parametru id do URL zapytania +function openNewTab() { + newWindow = window.open("about:blank", "_blank", ""); +} +function checkForNewAddress() { const apiUrl = id ? `/api/get?id=${encodeURIComponent(id)}` : "/api/get"; fetch(apiUrl, { @@ -39,7 +76,7 @@ function checkForNewAddress() { const a = document.getElementById("url"); a.href = url; a.textContent = url; - console.log(newWindow); + if (newWindow) { console.log("ustawiono nowy adres"); newWindow.location.href = id @@ -47,9 +84,16 @@ function checkForNewAddress() { : "/api/url"; } - document.getElementById("info").textContent = + info.textContent = "The page has opened; if not, click the link below. Link waiting is disabled."; - clearInterval(fetchingData); + + if (!autoListen.checked) { + clearInterval(fetchingData); + listening = false; + document.getElementById("startBtn").textContent = "Start listening"; + } else { + openNewTab(); + } } }) .catch((error) => { diff --git a/run_container.sh b/run_container.sh index 5f05750..f4f998a 100755 --- a/run_container.sh +++ b/run_container.sh @@ -1,50 +1,66 @@ -#!/bin/sh +#!/bin/bash -# Author:Mateusz Kędziora https://mkedziora.pl - -# Nazwa projektu PROJECT_NAME="fast-links" - -# Domyślny port DEFAULT_PORT=8080 # Funkcja wyświetlająca sposób użycia usage() { - echo "Użycie: $0 [-p port]" - echo " -p port Port na którym ma działać aplikacja (domyślnie: $DEFAULT_PORT)" + echo "Użycie: $0 [opcje]" + echo "Opcje:" + echo " -p, --port PORT Port na którym ma działać aplikacja (domyślnie: $DEFAULT_PORT)" + echo " -b, --build Wymuś przebudowanie obrazu" + echo " -d, --down Zatrzymaj i usuń kontenery" exit 1 } +# Domyślne wartości +BUILD_FLAG="" +PORT=$DEFAULT_PORT +ACTION="up" + # Przetwarzanie argumentów -while getopts ":p:" opt; do - case ${opt} in - p ) - PORT=$OPTARG +ARGS=$(getopt -o p:bd --long port:,build,down -n "$0" -- "$@") +eval set -- "$ARGS" + +while true; do + case "$1" in + -p|--port) + PORT="$2" + shift 2 ;; - \? ) + -b|--build) + BUILD_FLAG="--build" + shift + ;; + -d|--down) + ACTION="down" + shift + ;; + --) + shift + break + ;; + *) usage ;; esac done -# Jeśli port nie został podany, użyj domyślnego -PORT=${PORT:-$DEFAULT_PORT} +# Eksportuj zmienne środowiskowe +export PROJECT_NAME +export PORT -# Zatrzymaj i usuń stary kontener, jeśli istnieje -echo "Zatrzymywanie i usuwanie starego kontenera..." -docker stop $PROJECT_NAME 2>/dev/null -docker rm $PROJECT_NAME 2>/dev/null - -# Zbuduj nowy obraz -echo "Budowanie nowego obrazu..." -docker build -t $PROJECT_NAME . - -# Uruchom nowy kontener -echo "Uruchamianie nowego kontenera na porcie $PORT..." -docker run -d --name $PROJECT_NAME -p $PORT:8080 $PROJECT_NAME - -# Wyświetl informacje o uruchomionym kontenerze -echo "Kontener uruchomiony. Szczegóły:" -docker ps --filter name=$PROJECT_NAME - -echo "Aplikacja dostępna pod adresem: http://localhost:$PORT" \ No newline at end of file +# Wykonaj akcję +if [ "$ACTION" == "down" ]; then + echo "Zatrzymywanie i usuwanie kontenerów..." + docker compose down +else + echo "Uruchamianie kontenera na porcie $PORT..." + docker compose up -d $BUILD_FLAG + + # Wyświetl informacje o uruchomionym kontenerze + echo "Kontener uruchomiony. Szczegóły:" + docker compose ps + + echo "Aplikacja dostępna pod adresem: http://0.0.0.0:$PORT" +fi \ No newline at end of file