feat(homarr): make apps list configurable with auto-layout
This commit is contained in:
parent
d4eaa5f12c
commit
c1c1a84591
3 changed files with 101 additions and 60 deletions
|
|
@ -54,4 +54,32 @@ homarr_use_ssl: true
|
||||||
# Local admin
|
# Local admin
|
||||||
homarr_admin_username: "admin"
|
homarr_admin_username: "admin"
|
||||||
homarr_admin_email: "admin@digitalboard.ch"
|
homarr_admin_email: "admin@digitalboard.ch"
|
||||||
homarr_admin_password: "ChangeMe123!"
|
homarr_admin_password: "ChangeMe123!"
|
||||||
|
|
||||||
|
# Applications shown on the default board.
|
||||||
|
# Each app needs id, name, description, icon, href and a width (1-10).
|
||||||
|
# Height defaults to 1, can be increased for taller tiles.
|
||||||
|
# Apps are automatically packed left-to-right into the desktop grid (10 cols),
|
||||||
|
# scaled to tablet (6 cols) and mobile (2 cols).
|
||||||
|
homarr_apps:
|
||||||
|
- id: nextcloud
|
||||||
|
name: Nextcloud
|
||||||
|
description: Cloud Storage & Collaboration
|
||||||
|
icon: https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons/png/nextcloud.png
|
||||||
|
href: https://cloud.digitalboard.ch
|
||||||
|
width: 2
|
||||||
|
height: 1
|
||||||
|
- id: keycloak
|
||||||
|
name: Keycloak
|
||||||
|
description: Identity & Access Management
|
||||||
|
icon: https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons/png/keycloak.png
|
||||||
|
href: https://auth.digitalboard.ch
|
||||||
|
width: 2
|
||||||
|
height: 1
|
||||||
|
- id: mailman
|
||||||
|
name: Mailman
|
||||||
|
description: Mailing List Manager
|
||||||
|
icon: https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons/png/mailman.png
|
||||||
|
href: https://lists.digitalboard.ch
|
||||||
|
width: 2
|
||||||
|
height: 1
|
||||||
|
|
@ -26,6 +26,18 @@
|
||||||
Set via OpenBao or remove 'oidc' from homarr_auth_providers.
|
Set via OpenBao or remove 'oidc' from homarr_auth_providers.
|
||||||
when: "'oidc' in homarr_auth_providers"
|
when: "'oidc' in homarr_auth_providers"
|
||||||
|
|
||||||
|
- name: Validate homarr_apps have unique ids
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- homarr_apps | map(attribute='id') | list | length ==
|
||||||
|
homarr_apps | map(attribute='id') | unique | list | length
|
||||||
|
fail_msg: >-
|
||||||
|
homarr_apps contains duplicate ids.
|
||||||
|
Each app must have a unique 'id'. Got:
|
||||||
|
{{ homarr_apps | map(attribute='id') | list }}
|
||||||
|
success_msg: All app ids are unique
|
||||||
|
when: homarr_apps | length > 0
|
||||||
|
|
||||||
# =====================================================================
|
# =====================================================================
|
||||||
# 1. PREPARATION: packages and directories before container start
|
# 1. PREPARATION: packages and directories before container start
|
||||||
# =====================================================================
|
# =====================================================================
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,35 @@
|
||||||
|
{#-
|
||||||
|
Auto-layout packing macro.
|
||||||
|
|
||||||
|
Greedy left-to-right packing of apps into a grid with `cols` columns.
|
||||||
|
Returns the list of apps with computed x/y/w/h fields.
|
||||||
|
|
||||||
|
Width is clamped to cols (so an app wider than the grid is downsized
|
||||||
|
rather than overflowing). Height is taken as-is.
|
||||||
|
-#}
|
||||||
|
{%- macro pack(apps, cols) -%}
|
||||||
|
{%- set ns = namespace(x=0, y=0, row_h=0, out=[]) -%}
|
||||||
|
{%- for app in apps -%}
|
||||||
|
{%- set w = [app.width, cols] | min -%}
|
||||||
|
{%- set h = app.height | default(1) -%}
|
||||||
|
{%- if ns.x + w > cols -%}
|
||||||
|
{%- set ns.x = 0 -%}
|
||||||
|
{%- set ns.y = ns.y + ns.row_h -%}
|
||||||
|
{%- set ns.row_h = 0 -%}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- set _ = ns.out.append({'id': app.id, 'x': ns.x, 'y': ns.y, 'w': w, 'h': h}) -%}
|
||||||
|
{%- set ns.x = ns.x + w -%}
|
||||||
|
{%- if h > ns.row_h -%}
|
||||||
|
{%- set ns.row_h = h -%}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- endfor -%}
|
||||||
|
{{- ns.out | to_json -}}
|
||||||
|
{%- endmacro -%}
|
||||||
|
|
||||||
|
{%- set desktop_layout = pack(homarr_apps, 10) | from_json -%}
|
||||||
|
{%- set tablet_layout = pack(homarr_apps, 6) | from_json -%}
|
||||||
|
{%- set mobile_layout = pack(homarr_apps, 2) | from_json -%}
|
||||||
|
|
||||||
BEGIN TRANSACTION;
|
BEGIN TRANSACTION;
|
||||||
|
|
||||||
-- =====================================================================
|
-- =====================================================================
|
||||||
|
|
@ -129,82 +161,51 @@ VALUES
|
||||||
('board-default', 'group-credentials-admin', 'full-access');
|
('board-default', 'group-credentials-admin', 'full-access');
|
||||||
|
|
||||||
-- =====================================================================
|
-- =====================================================================
|
||||||
-- APPS
|
-- APPS (auto-generated from homarr_apps variable)
|
||||||
-- =====================================================================
|
-- =====================================================================
|
||||||
|
|
||||||
-- Nextcloud
|
{% if homarr_apps | length > 0 %}
|
||||||
|
{% for app in homarr_apps %}
|
||||||
INSERT OR IGNORE INTO app (id, name, description, icon_url, href)
|
INSERT OR IGNORE INTO app (id, name, description, icon_url, href)
|
||||||
VALUES (
|
VALUES (
|
||||||
'app-nextcloud',
|
'app-{{ app.id }}',
|
||||||
'Nextcloud',
|
'{{ app.name }}',
|
||||||
'Cloud Storage & Collaboration',
|
'{{ app.description | default("") }}',
|
||||||
'https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons/png/nextcloud.png',
|
'{{ app.icon }}',
|
||||||
'https://cloud.digitalboard.ch'
|
'{{ app.href }}'
|
||||||
);
|
);
|
||||||
|
|
||||||
INSERT OR IGNORE INTO item (id, board_id, kind, options, advanced_options)
|
INSERT OR IGNORE INTO item (id, board_id, kind, options, advanced_options)
|
||||||
VALUES (
|
VALUES (
|
||||||
'item-nextcloud',
|
'item-{{ app.id }}',
|
||||||
'board-default',
|
'board-default',
|
||||||
'app',
|
'app',
|
||||||
'{"json": {"appId": "app-nextcloud"}}',
|
'{"json": {"appId": "app-{{ app.id }}"}}',
|
||||||
'{"json": {}}'
|
'{"json": {}}'
|
||||||
);
|
);
|
||||||
|
|
||||||
INSERT OR REPLACE INTO item_layout (item_id, section_id, layout_id, x_offset, y_offset, width, height)
|
{% endfor %}
|
||||||
VALUES
|
|
||||||
('item-nextcloud', 'section-apps', 'layout-desktop', 0, 0, 2, 1),
|
|
||||||
('item-nextcloud', 'section-apps', 'layout-tablet', 0, 0, 2, 1),
|
|
||||||
('item-nextcloud', 'section-apps', 'layout-mobile', 0, 0, 1, 1);
|
|
||||||
|
|
||||||
-- Keycloak
|
|
||||||
INSERT OR IGNORE INTO app (id, name, description, icon_url, href)
|
|
||||||
VALUES (
|
|
||||||
'app-keycloak',
|
|
||||||
'Keycloak',
|
|
||||||
'Identity & Access Management',
|
|
||||||
'https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons/png/keycloak.png',
|
|
||||||
'https://auth.digitalboard.ch'
|
|
||||||
);
|
|
||||||
|
|
||||||
INSERT OR IGNORE INTO item (id, board_id, kind, options, advanced_options)
|
|
||||||
VALUES (
|
|
||||||
'item-keycloak',
|
|
||||||
'board-default',
|
|
||||||
'app',
|
|
||||||
'{"json": {"appId": "app-keycloak"}}',
|
|
||||||
'{"json": {}}'
|
|
||||||
);
|
|
||||||
|
|
||||||
INSERT OR REPLACE INTO item_layout (item_id, section_id, layout_id, x_offset, y_offset, width, height)
|
INSERT OR REPLACE INTO item_layout (item_id, section_id, layout_id, x_offset, y_offset, width, height)
|
||||||
VALUES
|
VALUES
|
||||||
('item-keycloak', 'section-apps', 'layout-desktop', 2, 0, 2, 1),
|
{% for entry in desktop_layout %}
|
||||||
('item-keycloak', 'section-apps', 'layout-tablet', 2, 0, 2, 1),
|
('item-{{ entry.id }}', 'section-apps', 'layout-desktop', {{ entry.x }}, {{ entry.y }}, {{ entry.w }}, {{ entry.h }}){% if not loop.last %},{% endif %}
|
||||||
('item-keycloak', 'section-apps', 'layout-mobile', 1, 0, 1, 1);
|
{% endfor %}
|
||||||
|
;
|
||||||
-- Mailman
|
|
||||||
INSERT OR IGNORE INTO app (id, name, description, icon_url, href)
|
|
||||||
VALUES (
|
|
||||||
'app-mailman',
|
|
||||||
'Mailman',
|
|
||||||
'Mailing List Manager',
|
|
||||||
'https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons/png/mailman.png',
|
|
||||||
'https://lists.digitalboard.ch'
|
|
||||||
);
|
|
||||||
|
|
||||||
INSERT OR IGNORE INTO item (id, board_id, kind, options, advanced_options)
|
|
||||||
VALUES (
|
|
||||||
'item-mailman',
|
|
||||||
'board-default',
|
|
||||||
'app',
|
|
||||||
'{"json": {"appId": "app-mailman"}}',
|
|
||||||
'{"json": {}}'
|
|
||||||
);
|
|
||||||
|
|
||||||
INSERT OR REPLACE INTO item_layout (item_id, section_id, layout_id, x_offset, y_offset, width, height)
|
INSERT OR REPLACE INTO item_layout (item_id, section_id, layout_id, x_offset, y_offset, width, height)
|
||||||
VALUES
|
VALUES
|
||||||
('item-mailman', 'section-apps', 'layout-desktop', 4, 0, 2, 1),
|
{% for entry in tablet_layout %}
|
||||||
('item-mailman', 'section-apps', 'layout-tablet', 4, 0, 2, 1),
|
('item-{{ entry.id }}', 'section-apps', 'layout-tablet', {{ entry.x }}, {{ entry.y }}, {{ entry.w }}, {{ entry.h }}){% if not loop.last %},{% endif %}
|
||||||
('item-mailman', 'section-apps', 'layout-mobile', 0, 1, 1, 1);
|
{% endfor %}
|
||||||
|
;
|
||||||
|
|
||||||
COMMIT;
|
INSERT OR REPLACE INTO item_layout (item_id, section_id, layout_id, x_offset, y_offset, width, height)
|
||||||
|
VALUES
|
||||||
|
{% for entry in mobile_layout %}
|
||||||
|
('item-{{ entry.id }}', 'section-apps', 'layout-mobile', {{ entry.x }}, {{ entry.y }}, {{ entry.w }}, {{ entry.h }}){% if not loop.last %},{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
;
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
Loading…
Add table
Add a link
Reference in a new issue