mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2025-04-20 15:04:57 +02:00
Solved OpenProject build bug
This commit is contained in:
parent
4b824ecd6c
commit
567622f523
2
ansible.cfg
Normal file
2
ansible.cfg
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
[defaults]
|
||||||
|
lookup_plugins = ./lookup_plugins
|
9
lookup_plugins/colorscheme.py
Normal file
9
lookup_plugins/colorscheme.py
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
from colorscheme_generator import generate_full_palette
|
||||||
|
|
||||||
|
class LookupModule(object):
|
||||||
|
def run(self, terms, variables=None, **kwargs):
|
||||||
|
base_color = terms[0]
|
||||||
|
count = kwargs.get('count', 100)
|
||||||
|
shades = kwargs.get('shades', True)
|
||||||
|
|
||||||
|
return [generate_full_palette(base_color, count=count, shades=shades)]
|
1
requirements.txt
Normal file
1
requirements.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
colorscheme-generator @ https://github.com/kevinveenbirkenbach/colorscheme-generator/archive/refs/tags/v0.2.0.zip
|
@ -1,8 +0,0 @@
|
|||||||
---
|
|
||||||
- name: rebuild custom openproject docker image
|
|
||||||
command:
|
|
||||||
cmd: docker build --no-cache -t {{custom_openproject_image}} .
|
|
||||||
chdir: "{{openproject_plugins_service}}"
|
|
||||||
environment:
|
|
||||||
COMPOSE_HTTP_TIMEOUT: 600
|
|
||||||
DOCKER_CLIENT_TIMEOUT: 600
|
|
@ -21,16 +21,14 @@
|
|||||||
src: Gemfile.plugins
|
src: Gemfile.plugins
|
||||||
dest: "{{openproject_plugins_service}}Gemfile.plugins"
|
dest: "{{openproject_plugins_service}}Gemfile.plugins"
|
||||||
notify:
|
notify:
|
||||||
- docker compose project setup
|
- docker compose project build and setup
|
||||||
- rebuild custom openproject docker image
|
|
||||||
|
|
||||||
- name: "Transfering Dockerfile to {{openproject_plugins_service}}Dockerfile"
|
- name: "Transfering Dockerfile to {{openproject_plugins_service}}Dockerfile"
|
||||||
template:
|
template:
|
||||||
src: Dockerfile
|
src: Dockerfile
|
||||||
dest: "{{openproject_plugins_service}}Dockerfile"
|
dest: "{{openproject_plugins_service}}Dockerfile"
|
||||||
notify:
|
notify:
|
||||||
- docker compose project setup
|
- docker compose project build and setup
|
||||||
- rebuild custom openproject docker image
|
|
||||||
|
|
||||||
- name: "include role docker-repository-setup for {{application_id}}"
|
- name: "include role docker-repository-setup for {{application_id}}"
|
||||||
include_role:
|
include_role:
|
||||||
|
@ -6,6 +6,9 @@ x-op-app: &app
|
|||||||
volumes:
|
volumes:
|
||||||
- "data:/var/openproject/assets"
|
- "data:/var/openproject/assets"
|
||||||
- "{{dummy_volume}}:/var/openproject/pgdata" # This mount is unnecessary and just done to prevent anonymous volumes
|
- "{{dummy_volume}}:/var/openproject/pgdata" # This mount is unnecessary and just done to prevent anonymous volumes
|
||||||
|
build:
|
||||||
|
context: {{openproject_plugins_service}}
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
|
||||||
services:
|
services:
|
||||||
{% include 'roles/docker-central-database/templates/services/' + database_type + '.yml.j2' %}
|
{% include 'roles/docker-central-database/templates/services/' + database_type + '.yml.j2' %}
|
||||||
|
@ -1,26 +1,34 @@
|
|||||||
# 🌍 Nginx Global Theming Role
|
# 🌍 Global CSS Injection for Nginx
|
||||||
|
|
||||||
This **Ansible role** provides a **global theming solution** for Nginx-based web applications. It ensures a **consistent look and feel** across multiple applications by injecting a **unified global.css** with customizable theming options.
|
## Description
|
||||||
---
|
|
||||||
|
|
||||||
## 🚀 Features
|
This Ansible role ensures **consistent global theming** across all Nginx-served applications by injecting a unified `global.css` file.
|
||||||
✅ **Automatic CSS Deployment** – Injects `global.css` into all Nginx-served applications.
|
The role leverages [`colorscheme-generator`](https://github.com/kevinveenbirkenbach/colorscheme-generator/) to generate a dynamic, customizable color palette for light and dark mode, compatible with popular web tools like **Bootstrap**, **Keycloak**, **Nextcloud**, **Taiga**, **Mastodon**, and many more.
|
||||||
✅ **Dynamic Theming** – Uses `design.css.colors` from Ansible variables for **full customization**.
|
|
||||||
✅ **Bootstrap Override Support** – Ensures Bootstrap-based apps use the **unified global styles**.
|
|
||||||
✅ **Versioning System** – Prevents caching issues with automatic **timestamp-based versioning**.
|
|
||||||
✅ **Dark Mode Support** – Automatically adapts to user preferences.
|
|
||||||
✅ **Runs Once Per Deployment** – Avoids redundant executions with `run_once_nginx_global_css`.
|
|
||||||
|
|
||||||
---
|
## Overview
|
||||||
|
|
||||||
## 🎨 Theming Details
|
This role deploys a centralized global stylesheet (`global.css`) that overrides the default theming of web applications served via Nginx. It's optimized to run only once per deployment and generates a **cache-busting version number** based on file modification timestamps.
|
||||||
|
It includes support for **dark mode**, **custom fonts**, and **extensive Bootstrap and UI component overrides**.
|
||||||
|
|
||||||
The **CSS template (`global.css.j2`)** dynamically applies the defined theme colors and ensures **Bootstrap, buttons, alerts, forms, and other UI elements** follow the **unified design**.
|
## Purpose
|
||||||
|
|
||||||
## 🛠️ Contribution
|
The goal of this role is to provide a **single source of truth for theming** across your infrastructure.
|
||||||
Feel free to **fork, modify, and improve** this role! Contributions are always welcome. 🛠️🔥
|
It makes all applications feel like part of the same ecosystem — visually and functionally.
|
||||||
|
|
||||||
---
|
## Features
|
||||||
|
|
||||||
🚀 **Happy Theming!** 🎨✨
|
- 🎨 **Dynamic Theming** via [`colorscheme-generator`](https://github.com/kevinveenbirkenbach/colorscheme-generator/)
|
||||||
*Created by [Kevin Veen-Birkenbach](https://www.veen.world) with the assistance of [ChatGPT](https://chatgpt.com/share/67a5fea3-4d5c-800f-8bc4-605712c02c9b).
|
- 📁 **Unified global.css** deployment for all Nginx applications
|
||||||
|
- 🌒 **Dark mode support** out of the box
|
||||||
|
- 🚫 **No duplication** – tasks run once per deployment
|
||||||
|
- ⏱️ **Versioning logic** to bust browser cache
|
||||||
|
- 🎯 **Bootstrap override compatibility**
|
||||||
|
- 🧩 **Theme support for Keycloak, Nextcloud, Gitea, LAM, Peertube, and more**
|
||||||
|
|
||||||
|
## Credits 📝
|
||||||
|
|
||||||
|
Developed and maintained by **Kevin Veen-Birkenbach**.
|
||||||
|
Learn more at [www.veen.world](https://www.veen.world)
|
||||||
|
|
||||||
|
Part of the [CyMaIS Project](https://github.com/kevinveenbirkenbach/cymais)
|
||||||
|
License: [CyMaIS NonCommercial License (CNCL)](https://s.veen.world/cncl)
|
||||||
|
@ -1,94 +0,0 @@
|
|||||||
import colorsys
|
|
||||||
|
|
||||||
def adjust_color(hex_color, target_lightness=None, lightness_change=0, hue_shift=0, saturation_change=0):
|
|
||||||
"""
|
|
||||||
Adjust a HEX color in HSL space.
|
|
||||||
|
|
||||||
- target_lightness: If provided (0 to 1), the lightness is set absolutely to this value.
|
|
||||||
Otherwise, lightness_change is applied additively (in percentage points, where 100 => 1 in HSL).
|
|
||||||
- lightness_change: Percentage points to add or subtract from lightness (if target_lightness is None).
|
|
||||||
- hue_shift: Degrees to shift hue (e.g., +180 for complementary).
|
|
||||||
- saturation_change: Percentage points to add or subtract from saturation.
|
|
||||||
|
|
||||||
Uses a 'cyclical' approach for lightness and saturation if no target_lightness is provided:
|
|
||||||
If the new value goes above 1, it wraps around (subtract 1).
|
|
||||||
If it goes below 0, it wraps around (add 1).
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Strip leading '#' if present
|
|
||||||
hex_color = hex_color.lstrip('#')
|
|
||||||
|
|
||||||
# Parse the original RGB values
|
|
||||||
r = int(hex_color[0:2], 16)
|
|
||||||
g = int(hex_color[2:4], 16)
|
|
||||||
b = int(hex_color[4:6], 16)
|
|
||||||
|
|
||||||
# Convert from [0..255] range to [0..1] for colorsys
|
|
||||||
r /= 255.0
|
|
||||||
g /= 255.0
|
|
||||||
b /= 255.0
|
|
||||||
|
|
||||||
# Convert RGB -> HLS (colorsys uses HLS, also hier: Hue, Lightness, Saturation)
|
|
||||||
h, l, s = colorsys.rgb_to_hls(r, g, b)
|
|
||||||
|
|
||||||
# Shift hue by (hue_shift / 360)
|
|
||||||
h = (h + (hue_shift / 360.0)) % 1.0
|
|
||||||
|
|
||||||
# Adjust saturation (cyclically)
|
|
||||||
s_new = s + (saturation_change / 100.0)
|
|
||||||
if s_new > 1:
|
|
||||||
s_new -= 1
|
|
||||||
elif s_new < 0:
|
|
||||||
s_new += 1
|
|
||||||
|
|
||||||
# Adjust lightness: either set to a target or change it additively (cyclically)
|
|
||||||
if target_lightness is not None:
|
|
||||||
l_new = target_lightness
|
|
||||||
else:
|
|
||||||
l_new = l + (lightness_change / 100.0)
|
|
||||||
if l_new > 1:
|
|
||||||
l_new -= 1
|
|
||||||
elif l_new < 0:
|
|
||||||
l_new += 1
|
|
||||||
|
|
||||||
# Convert back to RGB
|
|
||||||
new_r, new_g, new_b = colorsys.hls_to_rgb(h, l_new, s_new)
|
|
||||||
|
|
||||||
# Scale back to [0..255] and format as HEX
|
|
||||||
new_r = int(new_r * 255)
|
|
||||||
new_g = int(new_g * 255)
|
|
||||||
new_b = int(new_b * 255)
|
|
||||||
|
|
||||||
return '#{:02x}{:02x}{:02x}'.format(new_r, new_g, new_b)
|
|
||||||
|
|
||||||
def adjust_color_rgb(hex_color, target_lightness=None, lightness_change=0, hue_shift=0, saturation_change=0):
|
|
||||||
"""
|
|
||||||
Wrapper function for adjust_color.
|
|
||||||
|
|
||||||
Calls adjust_color to get the adjusted HEX color and then converts it to a string
|
|
||||||
of comma-separated RGB values.
|
|
||||||
"""
|
|
||||||
adjusted_hex = adjust_color(
|
|
||||||
hex_color,
|
|
||||||
target_lightness=target_lightness,
|
|
||||||
lightness_change=lightness_change,
|
|
||||||
hue_shift=hue_shift,
|
|
||||||
saturation_change=saturation_change
|
|
||||||
)
|
|
||||||
|
|
||||||
# Remove '#' and parse the RGB components
|
|
||||||
hex_val = adjusted_hex.lstrip('#')
|
|
||||||
r = int(hex_val[0:2], 16)
|
|
||||||
g = int(hex_val[2:4], 16)
|
|
||||||
b = int(hex_val[4:6], 16)
|
|
||||||
|
|
||||||
return f"{r},{g},{b}"
|
|
||||||
|
|
||||||
# Integration in the FilterModule for Ansible
|
|
||||||
class FilterModule(object):
|
|
||||||
'''Custom filters for Ansible'''
|
|
||||||
def filters(self):
|
|
||||||
return {
|
|
||||||
'adjust_color': adjust_color,
|
|
||||||
'adjust_color_rgb': adjust_color_rgb,
|
|
||||||
}
|
|
@ -1,2 +1,29 @@
|
|||||||
dependencies:
|
---
|
||||||
|
galaxy_info:
|
||||||
|
author: "Kevin Veen-Birkenbach"
|
||||||
|
description: "Global CSS injection for Nginx-based apps using dynamic colorschemes."
|
||||||
|
license: "CyMaIS NonCommercial License (CNCL)"
|
||||||
|
license_url: "https://s.veen.world/cncl"
|
||||||
|
company: |
|
||||||
|
Kevin Veen-Birkenbach
|
||||||
|
Consulting & Coaching Solutions
|
||||||
|
https://www.veen.world
|
||||||
|
min_ansible_version: "2.9"
|
||||||
|
platforms:
|
||||||
|
- name: Archlinux
|
||||||
|
versions:
|
||||||
|
- rolling
|
||||||
|
galaxy_tags:
|
||||||
- nginx
|
- nginx
|
||||||
|
- css
|
||||||
|
- colors
|
||||||
|
- bootstrap
|
||||||
|
- theming
|
||||||
|
- dynamic
|
||||||
|
- frontend
|
||||||
|
- global
|
||||||
|
repository: https://s.veen.world/cymais
|
||||||
|
issue_tracker_url: https://s.veen.world/cymaisissues
|
||||||
|
documentation: https://s.veen.world/cymais
|
||||||
|
dependencies:
|
||||||
|
- role: nginx
|
@ -1,26 +1,33 @@
|
|||||||
# Load this role via nginx-modifier-all for consistency
|
# Load this role via nginx-modifier-all for consistency
|
||||||
|
|
||||||
- name: Deploy global.css from template
|
# roles/nginx-modifier-css/tasks/main.yml
|
||||||
|
|
||||||
|
- name: Generate color palette with colorscheme-generator
|
||||||
|
set_fact:
|
||||||
|
color_palette: "{{ lookup('colorscheme', global_css_base_color, count=global_css_count, shades=global_css_shades) }}"
|
||||||
|
when: run_once_nginx_global_css is not defined
|
||||||
|
|
||||||
|
- name: Deploy global.css
|
||||||
template:
|
template:
|
||||||
src: global.css.j2
|
src: global.css.j2
|
||||||
dest: "{{global_css_destination}}"
|
dest: "{{ global_css_destination }}"
|
||||||
owner: "{{nginx.user}}"
|
owner: "{{ nginx.user }}"
|
||||||
group: "{{nginx.user}}"
|
group: "{{ nginx.user }}"
|
||||||
mode: '0644'
|
mode: '0644'
|
||||||
when: run_once_nginx_global_css is not defined
|
when: run_once_nginx_global_css is not defined
|
||||||
|
|
||||||
- name: Get stat for global.css destination file
|
- name: Get stat for global.css
|
||||||
stat:
|
stat:
|
||||||
path: "{{ global_css_destination }}"
|
path: "{{ global_css_destination }}"
|
||||||
register: global_css_stat
|
register: global_css_stat
|
||||||
when: run_once_nginx_global_css is not defined
|
when: run_once_nginx_global_css is not defined
|
||||||
|
|
||||||
- name: Set global_css_version to file modification time
|
- name: Set global_css_version
|
||||||
set_fact:
|
set_fact:
|
||||||
global_css_version: "{{ global_css_stat.stat.mtime }}"
|
global_css_version: "{{ global_css_stat.stat.mtime }}"
|
||||||
when: run_once_nginx_global_css is not defined
|
when: run_once_nginx_global_css is not defined
|
||||||
|
|
||||||
- name: Mark global css tasks as run once
|
- name: Mark css as done
|
||||||
set_fact:
|
set_fact:
|
||||||
run_once_nginx_global_css: true
|
run_once_nginx_global_css: true
|
||||||
when: run_once_nginx_global_css is not defined
|
when: run_once_nginx_global_css is not defined
|
File diff suppressed because it is too large
Load Diff
@ -1 +1,4 @@
|
|||||||
global_css_destination: "{{nginx.directories.data.global}}global.css"
|
global_css_destination: "{{nginx.directories.data.global}}global.css"
|
||||||
|
global_css_base_color: "{{ design.css.colors.base }}"
|
||||||
|
global_css_count: 100
|
||||||
|
global_css_shades: true
|
Loading…
x
Reference in New Issue
Block a user