{#- 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; -- ===================================================================== -- SERVER SETTINGS -- ===================================================================== INSERT OR REPLACE INTO serverSetting (setting_key, value) VALUES ('analytics', '{"json": {"enableGeneral": false, "enableWidgetData": false, "enableIntegrationData": false, "enableUserData": false}}'), ('culture', '{"json": {"defaultLocale": "de"}}'), ('crawling', '{"json": {"crawlingEnabled": false}}'), ('board', '{"json": {"homeBoardId": "board-default", "mobileHomeBoardId": "board-default", "enableStatusByDefault": true, "forceDisableStatus": false, "defaultBoardId": "board-default"}}'); -- Skip onboarding wizard UPDATE onboarding SET step = 'finish', previous_step = 'settings'; -- ===================================================================== -- GROUPS (must exist before groupMember) -- ===================================================================== -- OIDC admin group INSERT OR IGNORE INTO "group" (id, name, owner_id, position) VALUES ('group-oidc-admins', '{{ homarr_oidc_admin_group }}', NULL, 0); INSERT OR IGNORE INTO groupPermission (group_id, permission) VALUES ('group-oidc-admins', 'admin'), ('group-oidc-admins', 'board-create'), ('group-oidc-admins', 'board-full-access'), ('group-oidc-admins', 'integration-create'), ('group-oidc-admins', 'integration-full-access'); -- Credentials admin group INSERT OR IGNORE INTO "group" (id, name, owner_id, position) VALUES ('group-credentials-admin', 'credentials-admin', NULL, 1); INSERT OR IGNORE INTO groupPermission (group_id, permission) VALUES ('group-credentials-admin', 'admin'), ('group-credentials-admin', 'board-create'), ('group-credentials-admin', 'board-full-access'), ('group-credentials-admin', 'integration-create'), ('group-credentials-admin', 'integration-full-access'); -- ===================================================================== -- LOCAL ADMIN USER -- ===================================================================== INSERT OR IGNORE INTO user (id, name, email, password, email_verified, provider) VALUES ( 'user-local-admin', '{{ homarr_admin_username }}', '{{ homarr_admin_email }}', '{{ homarr_bcrypt_hash }}', 1, 'credentials' ); -- Assign admin user to groups INSERT OR IGNORE INTO groupMember (group_id, user_id) VALUES ('group-credentials-admin', 'user-local-admin'), ('group-oidc-admins', 'user-local-admin'); -- ===================================================================== -- BOARD -- ===================================================================== INSERT OR IGNORE INTO board ( id, name, is_public, primary_color, secondary_color, opacity, background_image_attachment, background_image_repeat, background_image_size, item_radius, disable_status ) VALUES ( 'board-default', '{{ homarr_default_board_name }}', {% if homarr_default_board_public %}1{% else %}0{% endif %}, '#fa5252', '#fd7e14', 100, 'fixed', 'no-repeat', 'cover', 'lg', 0 ); -- Layouts INSERT OR IGNORE INTO layout (id, name, board_id, column_count, breakpoint) VALUES ('layout-desktop', 'Desktop', 'board-default', 10, 0), ('layout-tablet', 'Tablet', 'board-default', 6, 768), ('layout-mobile', 'Mobile', 'board-default', 2, 480); -- Set home board for admin user (board exists now) UPDATE user SET home_board_id = 'board-default', mobile_home_board_id = 'board-default' WHERE id = 'user-local-admin'; -- ===================================================================== -- SECTION -- ===================================================================== DELETE FROM section_layout WHERE section_id = 'section-apps'; DELETE FROM item_layout WHERE section_id = 'section-apps'; DELETE FROM section WHERE id = 'section-apps'; INSERT INTO section (id, board_id, kind, x_offset, y_offset, name, options) VALUES ( 'section-apps', 'board-default', 'empty', 0, 0, 'Applications', '{"json": {}}' ); INSERT OR REPLACE INTO section_layout (section_id, layout_id, parent_section_id, x_offset, y_offset, width, height) VALUES ('section-apps', 'layout-desktop', NULL, 0, 0, 10, 3), ('section-apps', 'layout-tablet', NULL, 0, 0, 6, 4), ('section-apps', 'layout-mobile', NULL, 0, 0, 2, 6); -- Board permissions INSERT OR IGNORE INTO boardGroupPermission (board_id, group_id, permission) VALUES ('board-default', 'group-oidc-admins', 'full-access'), ('board-default', 'group-credentials-admin', 'full-access'); -- ===================================================================== -- APPS (auto-generated from homarr_apps variable) -- ===================================================================== {% if homarr_apps | length > 0 %} {% for app in homarr_apps %} INSERT OR IGNORE INTO app (id, name, description, icon_url, href) VALUES ( 'app-{{ app.id }}', '{{ app.name }}', '{{ app.description | default("") }}', '{{ app.icon }}', '{{ app.href }}' ); INSERT OR IGNORE INTO item (id, board_id, kind, options, advanced_options) VALUES ( 'item-{{ app.id }}', 'board-default', 'app', '{"json": {"appId": "app-{{ app.id }}"}}', '{"json": {}}' ); {% endfor %} INSERT OR REPLACE INTO item_layout (item_id, section_id, layout_id, x_offset, y_offset, width, height) VALUES {% for entry in desktop_layout %} ('item-{{ entry.id }}', 'section-apps', 'layout-desktop', {{ entry.x }}, {{ entry.y }}, {{ entry.w }}, {{ entry.h }}){% if not loop.last %},{% endif %} {% endfor %} ; INSERT OR REPLACE INTO item_layout (item_id, section_id, layout_id, x_offset, y_offset, width, height) VALUES {% for entry in tablet_layout %} ('item-{{ entry.id }}', 'section-apps', 'layout-tablet', {{ entry.x }}, {{ entry.y }}, {{ entry.w }}, {{ entry.h }}){% if not loop.last %},{% endif %} {% endfor %} ; 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;