Windows
Overview
End users in large enterprises often have multi-monitor setups on which they arrange the necessary apps in the most convenient way for executing daily tasks. The io.Connect Desktop Layouts feature allows them to save and later restore the exact arrangement and context of their environment - windows, apps, Workspaces, and their bounds and context. Users can save multiple apps and Workspaces in different Layouts, each corresponding to a specific task or workflow. Restoring the saved Layout happens with a single click and saves time and effort for finding, launching and arranging the desired apps. It's also possible to choose a default Global Layout that io.Connect Desktop will load upon startup.
The Layouts library has the following capabilities:
- importing, exporting, removing and getting Layouts;
- saving and restoring Layouts;
- hibernating and resuming Layouts (a quicker way to save and restore Layouts at the expense of system resources);
- events related to adding, removing, changing or saving Layouts;
The io.Connect Desktop Layouts library supports different types of Layouts:
- Global
This type of Layout can contain floating io.Connect Windows, io.Connect Window Groups, Workspaces. A Global Layout describes the bounds and context of all components participating in it.
- App Default
The default Layout of an app instance describes the last saved window bounds, the window state (maximized, minimized, normal), whether the window is collapsed and the default window context.
- Workspace
The Layout of a Workspace instance describes the arrangement of the Workspace elements, its bounds and the context of the apps participating in it.
Default Global Layout
A default Global Layout is an already saved arrangement of interop-enabled apps that is restored upon startup of io.Connect Desktop. Often users need the same set of starting apps when fulfilling daily routines. Setting up a default Global Layout will save them the time and effort they usually spend in finding, starting and arranging the required apps on system start or restart.
To disable automatic restore of the default Global Layout, use the "restoreDefaultGlobalOnStartup" property of the "layouts" top-level key in the system.json system configuration file of io.Connect Desktop:
{
"layouts": {
"restoreDefaultGlobalOnStartup": false
}
}The default Global Layout can be restored programmatically at a later stage if necessary, using the Layouts API:
const defaultLayout = await io.layouts.v2.default.get();
if (defaultLayout) {
await io.layouts.v2.restore(defaultLayout);
}Bypassing App Default Layouts
The App Default Layout contains information about:
- the last saved window bounds - size and location;
- the window state - maximized, minimized or normal and whether it's collapsed;
- the default window context;
When an app is started for the first time by io.Connect Desktop, the size and the location of the app window are determined by the bounds set in the app definition file (or by the default bounds, if none are specified in the app definition). When the user moves or resizes the app window and closes it, the new bounds are automatically saved as an App Default Layout and the next time the app is started, its window will be loaded using these bounds.
Sometimes, it may be necessary to bypass the App Default Layout - e.g., if somehow the app window has been saved outside the visible monitor area, or you simply want your app to always start with certain bounds, state or context despite the user interactions.
To bypass the App Default Layout only once, press and hold the SHIFT key and click on the app in the io.Connect launcher to start it.
To instruct io.Connect Desktop to always ignore the App Default Layout for your app, use the "ignoreSavedLayout" top-level key in the app definition file:
{
"ignoreSavedLayout": true
}Layout Loader
The default loader for Global Layouts is an HTML file located in the <installation_location>/interop.io/io.Connect Desktop/Desktop/assets/loader folder which you can replace with your own custom one or edit it directly.
To customize the Layout loader, use the "splash" property of the "layouts" top-level key in the system.json system configuration file of io.Connect Desktop.
The "splash" object has the following properties:
| Property | Type | Description |
|---|---|---|
"disabled" |
boolean |
If true, the Layout loader will be disabled. |
"height" |
number |
Height in pixels for the Layout loader. |
"title" |
string |
Title for the Layout loader. |
"url" |
string |
URL pointing to the location of the Layout loader. You can use environment variables. Defaults to "file:///%IO_CD_ASSETS_DIR%/loader/index.html". |
"width" |
number |
Width in pixels for the Layout loader. |
The following example demonstrates how to provide a custom loader and settings for it:
{
"layouts": {
"splash": {
"url": "https://example.com/my-custom-loader/index.html",
"title": "My Custom Loader",
"width": 500,
"height": 300
}
}
}Layout Stores
io.Connect Desktop can obtain Layouts from a local store, from a remote REST service, or from io.Manager. It's also possible to configure io.Connect Desktop to use an in-memory Layout store.
In the standard io.Connect Desktop deployment model, Layouts aren't stored locally on the user machine, but are served remotely. If io.Connect Desktop is configured to use a remote Layout store, it will poll it periodically and discover new Layouts. The store implementation is usually connected to an entitlement system based on which different users can have different Layouts.
The settings for the Layout stores are defined in the system.json system configuration file of io.Connect Desktop, under the "layouts" top-level key, which accepts an object with a "store" property as a value.
The "store" object has the following properties:
| Property | Type | Description |
|---|---|---|
"rejectUnauthorized" |
boolean |
If true (default), SSL validation will be enabled for the REST server. Valid only in "rest" mode. |
"restClientAuth" |
"no-auth" | "negotiate" | "kerberos" |
Authentication configuration. Defaults to "negotiate". Valid only in "rest" mode. |
"restFetchInterval" |
number |
Interval in seconds at which to poll the REST service for updates. Valid only in "rest" mode. Defaults to 60. |
"restURL" |
string |
URL pointing to the Layout store. Valid only in "rest" mode. Required if "type" is set to "rest". |
"type" |
"file" | "rest" | "server" | "in-memory" |
Type of the Layout store. Set to "file" (default) to read Layouts from a local file. Set to "rest" to fetch Layouts from a REST service. Set to "server" to fetch Layouts from io.Manager. Set to "in-memory" to use an in-memory Layout store. When io.Connect Desktop is connected to io.Manager, io.Manager is used as a Layout store by default. |
Local
By default, the Layouts are saved to and loaded from a local Layout store located in the <installation_location>/interop.io/io.Connect Desktop/UserData/<ENV>-<REG>/layouts folder where <ENV>-<REG> represents the environment and region of io.Connect Desktop (e.g., DEMO-INTEROP.IO). There you can store, customize, and delete your Layout files locally.
To instruct io.Connect Desktop to manage Layouts as local files, set the "type" property of the "store" object to "file":
{
"layouts" : {
"store": {
"type": "file"
}
}
}REST
Layout definitions can also be obtained from remote Layout stores via a REST service.
ℹ️ For a reference implementation of a remote Layout definitions store, see the Node.js REST Config example.
To configure a connection to the REST service providing the Layout store, set the "type" property of the "store" object to "rest" and provide the URL of the REST service:
{
"layouts": {
"store": {
"type": "rest",
"restURL": "https://my-rest-service/layouts",
"restFetchInterval": 20,
"restClientAuth": "no-auth"
}
}
}The remote store must return Layout definitions in the following response shape:
{
"layouts": [
// List of Layout definition objects.
{}, {}
]
}io.Manager
You can also use io.Manager for hosting and retrieving Layouts.
When io.Connect Desktop is connected to io.Manager, it uses io.Manager as a Layout store by default:
{
"server": {
"enabled": true,
"url": "https://my-io-manager.com/api"
}
}ℹ️ For details on how to configure io.Connect Desktop to connect to io.Manager, see the io.Manager section.
In this case, io.Manager takes precedence over the Layout store specified in the "store" object under the "layouts" top-level key. To use a different Layout store while connected to io.Manager, set the "layoutsStore" property of the "features" object under the "server" top-level key to false:
{
"server": {
"enabled": true,
"url": "https://my-io-manager.com/api",
"features": {
"layoutsStore": false
}
},
"layouts": {
"store": {
"type": "rest",
"restURL": "https://my-rest-service/layouts"
}
}
}⚠️ Note that when using io.Manager as a Layout store, Layout files aren't only fetched from the server, but are also saved on the server (e.g., when the user edits and saves an existing Layout).
In-Memory
Available since io.Connect Desktop 9.4
Configuring io.Connect Desktop to use an in-memory store for Layouts means that the user will be able to perform all available Layout operations (such as saving and restoring Layouts), but all Layouts will be available only during the current session. When the io.Connect platform is restarted, the in-memory Layout store will be empty.
The in-memory Layout store may be useful in cases where you have your own custom Layout service which imports Layouts on system startup and exports them on system shutdown allowing you to persist Layouts across user sessions.
To configure io.Connect Desktop to use an in-memory Layout store, set the "type" property of the "store" object to "in-memory":
{
"layouts" : {
"store": {
"type": "in-memory"
}
}
}Layout Sharing
Available since io.Connect Desktop 10.5
Layout sharing via io.Manager enables users to:
- Share Global and Workspace Layouts with other users and groups with view or edit permissions.
- Save private copies of shared and public Layouts.
- Organize Layouts in folders.
- Share Layouts and manage the access to them from the Launchpad and from the Workspace tab menu of the Workspaces App.
Apps can retrieve the access information for Layouts and change the access to them by using the Layouts API.
The following demonstrates using the Launchpad and the Workspaces App tab menu UI options for publishing and managing Global and Workspace Layouts:
In io.Manager, Layouts are classified as private, shared, or public:
- Private Layouts are available only to their owner.
- Shared Layouts are available to their owner and to the users and groups with which they have been shared with view or edit permissions. Publishing a private Layout from the Launchpad or the Workspaces App creates a shared Layout.
- Public Layouts are available to all users and can be edited by their owner and by the users and groups that have been granted edit permissions for them in io.Manager. Public Layouts can't be created from the Launchpad or the Workspaces App - they can be created only via io.Manager or by apps using the new Layouts API.
The Launchpad and the Workspaces App don't distinguish between shared and public Layouts. The Launchpad displays both shared and public Layouts in the "Public" section. The Workspaces App marks shared and public Workspace Layouts with "Public Workspace".
⚠️ Note that, currently, the access to a public Layout can be restricted by adding users and groups with view permissions to it from the Launchpad or the Workspaces App. This converts the public Layout to a shared Layout in io.Manager.
The following table describes the different types of Layout sharing entities and their permissions:
| Entity | Permissions |
|---|---|
| Owner | Can restore the Layout, save changes to it, change its name, folder, icon, and description, change the users and groups with access to it and their permissions, and delete it for all users. The owner of a Layout can be changed only via io.Manager. |
| Editor | Users and groups with edit permissions for the Layout. Can restore the Layout, save changes to it, change its name, folder, icon, and description, change the users and groups with access to it and their permissions, and delete it for all users. |
| Viewer | Users and groups with view permissions for the Layout. Can restore the Layout and save a private copy of it, but don't have edit permissions - can't save changes to it, change its name, folder, icon, description, or the users and groups with access to it. |
When Layout sharing is disabled, Layouts are identified by their name and type. When Layout sharing is enabled, Layouts are identified by unique IDs. The name of a private Layout must be unique only among the private Layouts of the same type of its owner, while the name of a shared or a public Layout must be unique among all shared and public Layouts of the same type. This means that a user can have a private and a shared Layout with the same name, but publishing a Layout will fail if a shared or a public Layout with the same name and type already exists.
The protocol handler options for restoring Layouts and Workspaces accept Layout IDs as well as names. This allows you to target a specific Layout when several Layouts with the same name and type are available.
Requirements
Layout sharing has the following requirements:
io.Manager 4.0 or later must be used as a Layout store. In the
system.jsonsystem configuration file of io.Connect Desktop, the"enabled"property of the"server"top-level key must be set totrueand the"layoutsStore"property of the"features"object must not be set tofalse(defaults totrue).Layout sharing (advanced Layouts) must be enabled both in io.Connect Desktop and in io.Manager. If it's enabled in only one of them, or if the io.Manager version doesn't support it, io.Connect Desktop will display an error and won't start.
All io.Connect Desktop instances connected to io.Manager must be version 10.5 or later. When Layout sharing is enabled in io.Manager, it provides only advanced Layouts to the platforms and rejects changes to legacy Layouts. The existing Layouts stored in io.Manager will become available as advanced Layouts only after they have been migrated via the "Migrate legacy layouts" page available in the "Layouts" section of the io.Manager Admin UI, or via the
POST /advancedLayouts/migration/runendpoint of the io.Manager Server REST API.Apps must use the new Layouts API available in
@interopio/desktop6.23 or later. When Layout sharing is enabled, the legacy Layouts API is unreliable - its methods for retrieving Layouts return empty arrays, its other methods (e.g., for saving, restoring, removing, and renaming Layouts) will throw errors, and its Layout events won't be raised. When Layout sharing is disabled, both Layouts APIs can be used simultaneously with all Layout stores.Custom Workspaces Apps must use
@interopio/workspaces-ui-react5.0 or later, and custom Launchpad apps must use@interopio/components-react5.0 or later in order to provide the Layout sharing options.
Configuration
To enable Layout sharing, use the "advancedLayouts" property of the "server" top-level key in the system.json system configuration file of io.Connect Desktop:
{
"server": {
"enabled": true,
"url": "https://my-io-manager.com/api",
"advancedLayouts": {
"enabled": true
}
}
}The "advancedLayouts" object has the following properties:
| Property | Type | Description |
|---|---|---|
"enabled" |
boolean |
If true, will enable Layout sharing. Defaults to false. |
To enable Layout sharing in io.Manager, set the enabled property of the advancedLayouts object in the configuration object for initializing the io.Manager Server to true, or set the API_ADVANCED_LAYOUTS_ENABLED environment variable to true. You can also use the sharingRequiredGroup property of the advancedLayouts object to allow only the members of specific groups to share and publish Layouts.
ℹ️ For more details, see the Capabilities > Layouts > Overview > Advanced Layouts, Configuration > Server > Configuration Object, and Configuration > Server > Environment Variables sections of the io.Manager documentation.
The Layouts are refreshed from io.Manager at the interval specified in the "fetchInterval" property of the "server" top-level key (defaults to 30 seconds). It isn't recommended to set this interval below the default value.