diff --git a/.env.example b/.env.example index 930af5b..a4e1ea9 100644 --- a/.env.example +++ b/.env.example @@ -41,7 +41,7 @@ OAUTH_ONLY=False # Space-separated OAuth2 scopes #OAUTH_SCOPE=openid profile email -# Database engine: 'sqlite' or 'postgres' +# Database engine: 'sqlite', 'postgres' or 'mariadb' DB_ENGINE=sqlite # PostgreSQL settings (only used when DB_ENGINE=postgres) @@ -51,5 +51,12 @@ DB_ENGINE=sqlite #DB_HOST=localhost #DB_PORT=5432 +# MariaDB settings (only used when DB_ENGINE=mariadb) +#DB_NAME=photo21 +#DB_USER=photo21 +#DB_PASSWORD= +#DB_HOST=localhost +#DB_PORT=3306 + # SQLite settings (only used when DB_ENGINE=sqlite) #DB_PATH=/app/data/db.sqlite3 diff --git a/docker-compose.yml b/docker-compose.yml index 001fed7..e93a4bc 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,15 +5,16 @@ networks: services: db: - image: postgres:16 + image: mariadb:11 container_name: photo26-db restart: unless-stopped environment: - POSTGRES_DB: photo26 - POSTGRES_USER: photo26 - POSTGRES_PASSWORD: change-me + MARIADB_DATABASE: photo26 + MARIADB_USER: photo26 + MARIADB_PASSWORD: change-me + MARIADB_RANDOM_ROOT_PASSWORD: "yes" volumes: - - ./postgres_data:/var/lib/postgresql/data + - ./mariadb_data:/var/lib/mysql networks: - photo26 @@ -24,12 +25,12 @@ services: depends_on: - db environment: - DB_ENGINE: postgres + DB_ENGINE: mariadb DB_NAME: photo26 DB_USER: photo26 DB_PASSWORD: change-me DB_HOST: db - DB_PORT: 5432 + DB_PORT: 3306 SECRET_KEY: change-me EXTRA_HOSTS: photos.example.org volumes: diff --git a/photo21/settings.py b/photo21/settings.py index 953a8c2..6a6b019 100644 --- a/photo21/settings.py +++ b/photo21/settings.py @@ -149,6 +149,20 @@ if _db_engine == "postgres": "PORT": config("DB_PORT", default="5432"), } } +elif _db_engine == "mariadb": + DATABASES = { + "default": { + "ENGINE": "django.db.backends.mysql", + "NAME": config("DB_NAME", default="photo21"), + "USER": config("DB_USER", default="photo21"), + "PASSWORD": config("DB_PASSWORD", default=""), + "HOST": config("DB_HOST", default="localhost"), + "PORT": config("DB_PORT", default="3306"), + "OPTIONS": { + "charset": "utf8mb4", + }, + } + } elif _db_engine == "sqlite": DATABASES = { "default": { @@ -160,7 +174,7 @@ elif _db_engine == "sqlite": } } else: - raise ValueError(f"Unknown DB_ENGINE '{_db_engine}'. Must be 'sqlite' or 'postgres'.") + raise ValueError(f"Unknown DB_ENGINE '{_db_engine}'. Must be 'sqlite', 'postgres' or 'mariadb'.") CACHES = { "default": { diff --git a/photo21/static/copy-button.js b/photo21/static/copy-button.js new file mode 100644 index 0000000..91f7ec8 --- /dev/null +++ b/photo21/static/copy-button.js @@ -0,0 +1,24 @@ +document.querySelectorAll('[data-clipboard-text]').forEach(function(btn) { + btn.addEventListener('click', function() { + var text = btn.dataset.clipboardText; + if (navigator.clipboard) { + navigator.clipboard.writeText(text); + } else { + var ta = document.createElement('textarea'); + ta.value = text; + ta.style.position = 'fixed'; + ta.style.opacity = '0'; + document.body.appendChild(ta); + ta.select(); + document.execCommand('copy'); + document.body.removeChild(ta); + } + var original = btn.textContent; + btn.textContent = '✓ Copied!'; + btn.disabled = true; + setTimeout(function() { + btn.textContent = original; + btn.disabled = false; + }, 2000); + }); +}); diff --git a/photo21/templates/base.html b/photo21/templates/base.html index 91f63cb..ccd17c2 100644 --- a/photo21/templates/base.html +++ b/photo21/templates/base.html @@ -37,6 +37,7 @@ SPDX-License-Identifier: GPL-3.0-or-later