.. _theme-commands:

Theme commands
----------------

.. _25.4|VOSS-1547:

Graphical user interface themes can be managed by means of
``theme`` commands available from the command line interface.

The full list of options are shown on the menu as:

::

   theme download <theme-name>                           - Download a theme to the media folder
   theme list                                            - Display a list of available themes
   theme set default <admin|selfservice> to <theme-name> - Set a theme as the system default
   theme show default [<admin|selfservice>]              - Show the current default theme for a profile
   theme upload media/<filename>                         - Upload a theme zip file from the media folder



.. note::

   On upgrade - all "default" theme changes will be overridden

.. note::

   * Theme uploads and downloads take place from and to the ``/opt/platform/admin/home/media/`` folder.
   * The theme download includes all settings and assets (images), not just the JSON configuration.
   * The theme upload restores the complete theme with all images and settings.
   * Uploads are only permitted from the admin media folder. Files outside this folder are rejected.
   * Uploads of Self-service themes are not be applied to the GUI, since such themes are managed by
     means of custom file uploads from the GUI.


.. rubric:: Primary node requirement

Theme management commands that modify data (``theme upload``, ``theme set default``) can only be 
executed on the primary application node. Attempting to run these commands on non-primary nodes 
results in a graceful error. Read-only commands (``theme list``, ``theme show default``) can be 
run on any node.


List themes
...........

All themes currently available on the user interface can be listed:

::

   $ theme list
   Themes:
          voss_platform   
          voss_selfservice 


Get default theme
..................

The theme currently set to be the default theme can be listed:

::

  $ theme show default
  admin: voss_platform   
  selfservice: voss_selfservice


Set default theme by interface
................................

You can set the default theme separately for each interface type (Administration and Self Service). 
This determines which theme is used for the login page of each interface.
The user interface **System Global Settings** are updated accordingly.

.. note::

   * Only system-level administrators can set the default themes for each interface type.
   * If an invalid theme name is specified, the transaction fails with an error message containing
     "Invalid foreign key". 

.. rubric:: Set default theme for Administration interface

To set the default theme for the Administration interface login page:

::

   $ theme set default admin to my_admin_theme
   Default theme for 'admin' set to: my_admin_theme

Verify the default was set correctly:

::

   $ theme show default admin
   my_admin_theme

.. rubric:: Set default theme for Self Service interface

To set the default theme for the Self Service interface login page:

::

   $ theme set default selfservice to my_selfservice_theme
   Default theme for 'selfservice' set to: my_selfservice_theme

Verify the default was set correctly:

::

   $ theme show default selfservice
   selfservice: my_selfservice_theme

.. rubric:: View all default themes

To view the current defaults for both interface types:

::

   $ theme show default
   admin: my_admin_theme
   selfservice: my_selfservice_theme

The interface type must be one of:

* ``admin`` - Sets the default theme for Administration interface login pages
* ``selfservice`` - Sets the default theme for Self Service interface login pages

Only one theme can be set as the default for each interface type at any time. Setting a new 
default theme automatically replaces the previous default for that interface. If no default is 
specified for an interface, the VOSS theme is used as the fallback.


Download theme
..............

By specifying a theme name as a ``.zip`` file prefix, a command is  available
to download the theme. The downloaded file includes all theme settings and assets:

::

  $ theme download tdkadmin
  Downloading theme 'tdkadmin' to: /opt/platform/admin/home/media/tdkadmin.zip
  Theme downloaded successfully to: /opt/platform/admin/home/media/tdkadmin.zip

The downloaded ``.zip`` file contains the ``theme.json`` file and an ``images/`` directory 
with all theme assets (logos, backgrounds, favicons). This allows for complete backup and 
migration of themes between system instances.


Upload theme
............


By specifying a ``.zip`` filename available in the ``/opt/platform/admin/home/media/`` directory,
a command is  available to upload this theme:

.. note::
       
   * Uploaded themes are distributed to cluster.
   * Uploads are only permitted from the admin media folder. Attempting to upload from outside 
     this folder results in an error.
   * Uploading a theme to the same hierarchy (the ``"hierarchy":`` value in the uploaded JSON file)
     as a theme with the same name will update (overwrite) the existing theme with the same name.
     If no hierarchy is specified, the theme is uploaded to the ``sys`` hierarchy.
   * Uploads of Self-service themes cannot be applied to the GUI -use the custom upload function
     in the GUI.

::

  $ theme upload /opt/platform/admin/home/media/new_full_theme.zip
  Uploading theme from: /opt/platform/admin/home/media/new_full_theme.zip
  Theme uploaded successfully!

  $ theme list
  Themes:
          default        
          new_full_theme 
          tdkadmin       
          voss_selfservice

The upload process restores the complete theme including all settings and images. If a theme 
with the same identifier (name) exists at the same hierarchy level, it is overwritten.

The uploaded theme can now also be inspected and verified on the GUI.
Refer to the Themes topic in the Core Guide.


Theme ``.zip`` file specification
...................................

The ``.zip`` file should contain:

- ``theme.json``: Standard export format with meta and resources
  
  For details on fields and values, refer to the Themes topic in the Core Guide.

  .. note::

     The value of the ``name`` attribute is mandatory and identifies the theme and
     may only contain characters in the range: ``[a-zA-Z0-9_]``.

   
- ``images/``: Directory containing theme images (for both light and dark mode, if configured)

For details on the ``.zip`` file content and structure, you can also download a
theme from the user interface and inspect it. Refer to the user interface 
and Themes topic in the Core 
Guide for details on colour code syntax,
allowed image sizes, allowed image names and image file types.

You can also refer to the details in the API Reference:

https://documentation.voss-solutions.com/release_25.4-PB0/html/src/api-ref/data_Theme-Model.html


Dark mode in theme JSON
........................

When a theme supports dark mode, the JSON includes:

- ``enable_dark_mode``: Boolean field set to ``true`` that enables dark mode functionality
- ``theme_customisation_dark_mode``: Separate block containing dark mode colors and images

If ``enable_dark_mode`` is ``false`` or not present, the theme operates in light mode only, 
and the ``theme_customisation_dark_mode`` block is ignored.

The fallback behavior for missing dark mode assets:

1. If a dark mode asset is empty, the light mode value is used
2. If both are empty, the default (VOSS) theme's appropriate variant is used

Example
.......

Images directory:

::

   images/
    favicon.ico
    logo.png
    login-logo.png
    login-background.png
    favicon-dark.ico       (optional dark mode favicon)
    logo-dark.png          (optional dark mode logo)
    login-logo-dark.png    (optional dark mode login logo)
    login-background-dark.png  (optional dark mode login background)

Theme JSON file:

``theme.json``

::

   {
     "meta": {},
     "resources": [
       {
        "meta": {
          "model_type": "data/Theme",
          "hierarchy": "my.hierarchy.path",
          "schema_version": "0.6.6"
        },
        "data": {
          "name": "My Theme Name",
          "title": "My Theme Title",
          "banner_title": "My Banner Title",
          "description": "My theme description",
          "enable_dark_mode": true,
          "theme_customisation_light_mode": {
            "primary_colour": "#000046",
            "primary_text_colour": "#ffffff",
            "accent_colour": "#007fb0",
            "accent_text_colour": "#ffffff",
            "panel_colour": "#f2f2f2",
            "button_background_colour": "#000046",
            "panel_text_colour": "#000000",
            "background_colour": "#e6e7e8",
            "info_notification_colour": "#00ade5",
            "info_notification_text_colour": "#ffffff",
            "success_notification_colour": "#68bd17",
            "success_notification_text_colour": "#ffffff",
            "warn_notification_colour": "#fbc403",
            "warn_notification_text_colour": "#000000",
            "error_notification_colour": "#dc0c00",
            "error_notification_text_colour": "#ffffff",
            "theme_font": "Roboto",
            "favicon": "favicon.ico",
            "logo": "logo.png",
            "login_logo": "login-logo.png",
            "login_bg": "login-background.png"
          },
          "theme_customisation_dark_mode": {
            "primary_colour": "#2e2d2f",
            "primary_text_colour": "#ffffff",
            "accent_colour": "#2aa7d6",
            "accent_text_colour": "#ffffff",
            "topbar_colour": "#000027",
            "topbar_text_colour": "#ffffff",
            "menu_colour": "#000027",
            "menu_text_colour": "#ffffff",
            "panel_colour": "#2e2d2f",
            "button_background_colour": "#000027",
            "panel_text_colour": "#ffffff",
            "input_colour": "#000000",
            "input_text_colour": "#ffffff",
            "background_colour": "#070b14",
            "info_notification_colour": "#00ade5",
            "info_notification_text_colour": "#031018",
            "success_notification_colour": "#68bd17",
            "success_notification_text_colour": "#000000",
            "warn_notification_colour": "#fbc403",
            "warn_notification_text_colour": "#000000",
            "error_notification_colour": "#dc0c00",
            "error_notification_text_colour": "#ffffff",
            "highlight_text_colour": "#ffffff",
            "panel_header_background_colour": "#3d3f47",
            "panel_header_text_colour": "#ffffff",
            "paginator_text_colour": "#ffffff",
            "theme_font": "Roboto",
            "favicon": "favicon-dark.ico",
            "logo": "logo-dark.png",
            "login_logo": "login-logo-dark.png",
            "login_bg": "login-background-dark.png"
          },
          "login_page": {
            "title": "My Login page title",
            "banner": "My login page banner"
          },
          "interface": "administration"
        }
       }
     ]
   }
