User Interface
This page describes the features of the ShinyProxy interface and the corresponding documentation.
Main page
After logging in, the user is redirected to the main page. This page contains a
list of apps. In addition, it is possible to show a list of the active apps of
the user. This list can be shown in two ways, controlled by
the proxy.my-apps-mode
option. If this option is set to Modal
, a
button My Apps
will appear in the navigation bar. After clicking this button,
a modal opens that shows the current active apps of the user. The other
possibility is to set the option to Inline
, in this case the active apps
are shown inline on the main page.
In order to show a notification message (or message of the day) to every user,
add the property proxy.notification-message
(HTML is supported), e.g.:
proxy:
notification-message: An <b>example</b> message!
App page
As the name suggests the app page is used to display a (running) app. With all features enabled this page can look like:
The only part of this page controlled by ShinyProxy is the navigation bar. The other part of the page displays the app in an iframe. The navigation bar contains (from left to right):
- the logo and title (see configuration)
- the username of the current logged-in user
- the
App details
button - the
Restart app
button - the
Stop app
button - the
Report issue
button, clicking on this button opens a popup where a user can report an issue to the administrator of the ShinyProxy server ( see configuration). - the
Admin
button which is only showed for admin users, clicking on this buttons opens the admin page. - the
Sign Out
button
Note: in case the app allows to open multiple instances,
the App details
, Restart app
, and Stop app
buttons are replaced by
the Switch instance
button.
App Details
Multiple pages in ShinyProxy have an App details
button, this button opens a
modal with all details of the relevant app:
When using app parameters, the modal shows the list of parameters together with the value selected by the user. When the app is inactive (i.e. not currently opened by a user), the modal also shows the remaining time of the heartbeat timeout setting. Similarly, when the max-lifetime setting is enabled, the modal shows the remaining lifetime.
Using multiple instances of an app
By default, ShinyProxy allows a user to only run one instance of an app at a given time. This means that a user cannot open a second instance of an app. Starting with ShinyProxy 2.6.0, it is possible to run multiple instances of an app.
There are two ways to control this behavior:
- by specifying the global
proxy.default-max-instances
option. By default, this option is set to one. Specifying a larger value allows the user to run the given amount of instances of any apps. This option allows you to specify the value-1
which allows a user to run unlimited instances of any app. - by specifying the
max-instances
option on a specification of an app. This overrides the global value provided inproxy.default-max-instances
, but only for this specific app. Again specifying the value-1
allows a user to run unlimited instances of any app.
proxy:
default-max-instances: 5
specs:
- id: 01_hello
display-name: Hello Application
container-cmd: [ "R", "-e", "shinyproxy::run_01_hello()" ]
container-image: openanalytics/shinyproxy-demo
max-instances: 1
- id: rstudio
display-name: RStudio
container-image: openanalytics/shinyproxy-rstudio-ide-demo:1.4.1106__4.0.4
container-env:
DISABLE_AUTH: true
WWW_ROOT_PATH: "#{proxy.getRuntimeValue('SHINYPROXY_PUBLIC_PATH')}"
port: 8787
The above example allows a user to run up to 5 instances of RStudio and one
instance of the hello application. When the user can run only one app, the
Switch instance
button is replaced by a Restart instance
and Stop instance
button.
After clicking on the Switch instance
button, a popup is shown where the user
can manage the instances of the app:
The popup lists the current active instances of the app. When clicking on the
link on the main page, the “Default” instance is opened. Every instance can be
stopped, but only the current open instance can be restarted. A new instance can
be opened by providing a name in the input field and clicking the Start
button, after which a new tab is opened with the new instance. This new instance
will be listed in the popup:
Note: the different instances of each app are fully isolated and are running
in a separate container. This also means that any inactive instances will be
cleaned up, independently of any other instance of the same app. A user can
stop apps themselves using the Switch instance
button, even for apps running
in a different tab of their browser.
Automatically reconnecting websockets
Many apps used in ShinyProxy use websockets for communicating with the backend server. Due to the nature of websockets, this connection can be disturbed by suboptimal WiFi connections, server restart etc. Therefore, ShinyProxy contains a mechanism for restoring this connection. However, since ShinyProxy does not know how an app internally works, this is a best-effort approach. Therefore, it is always better to use any reconnecting mechanism which is natively supported by the app. You can configure this option by specifying:
- the
proxy.default-webSocket-reconnection-mode
option: specifies the global reconnection mode. By default, this isNone
. - the
websocket-reconnection-mode
on a specification of an app. This overrides the global value provided inproxy.default-webSocket-reconnection-mode
, but only for this specific app. - the
shiny-force-full-reload
on a specification of an app. This controls whether ShinyProxy performs a full reload of the iframe or only tries to restore the websocket connection in case of a Shiny app.
The mode can be set to one of None
, Confirm
or Auto
. In the first case, the
mechanism is disabled and ShinyProxy will not try to restore the connection with
the app. Using Confirm
, ShinyProxy will first ask the user for confirmation
before trying to restore the connection. Using Auto
, ShinyProxy will
automatically try to reconnect to the app without asking the user for
confirmation.
When the mechanism is enabled and a websocket connection of the apps get interrupted, ShinyProxy notices this and starts the restore procedure. First of all, a message is shown to the user:
In the background ShinyProxy tries to restore the connection. When ShinyProxy
detects that the running application is a Shiny app, it uses the
$socket.reconnect()
function of the Shiny JavaScript API to restore the
connection. For all other apps, ShinyProxy reloads the iframe displaying the
app. The mechanism tries to restore the connection up to ten times. However,
between every attempt, ShinyProxy waits for an increasing amount of time. That
is, after the first attempt, it waits for two seconds, after the third for three
second and so on. If the app cannot be restored after 10 seconds, ShinyProxy
asks the user whether it should reload the complete page.
Note: you can tell ShinyProxy to reload the iframe instead of using the
special Shiny function ($socket.reconnect()
) by setting the
shiny-force-full-reload
option in the app specification to true
(see above).
As discussed earlier, the reconnecting mechanism is a best-effort approach. In an ideal case the app should be responsible for restoring the connection. The reason is that the developers of an app know better how to restore the websocket connection. It is not uncommon that extra actions must be taken care of when reconnecting. Such situations cannot be handled by ShinyProxy. Note that as a developer of a Shiny app, you can add native support for reconnecting.
The following table shows how the mechanism works in different situations. This should help an administrator on deciding whether to activate the mechanism.
Configuration | App characteristics | Result | ||||
---|---|---|---|---|---|---|
Enabled? | Force reload?¹ | Shiny app? | App supports reconnecting?² | Reconnect mechanism | App working after reload? | Data loss? |
Yes | No | Yes | No | $socket.reconnect() |
It It depends | Yes |
Yes | No | Yes | Yes | $socket.reconnect() |
Yes | No |
Yes | Yes | Yes | Yes or No | Reload iframe | Yes | Yes |
No | N/A | Yes | Yes or No | Do nothing | No | Yes |
Yes | N/A | No | No | Reload iframe | Yes | It Depends, but likely |
Yes | N/A | No | Yes | Reload iframe | Yes | It Depends, but likely |
No | N/A | No | Yes | Do nothing | Yes (after native reload) | No |
- ¹
shiny-force-full-reload
is enabled - ² in case of Shiny app, the code is written such that reload works properly. In case of another app, it has a native reconnect mechanism.
The short advice for an administrator is:
- when an app contains a native reconnecting mechanism -> do not enable the mechanism in ShinyProxy
- when an app does not contain a native reconnecting mechanism -> try enabling the
ShinyProxy mechanism and decide whether this works for your app. In case of a
Shiny app, you can also test whether enabling the
shiny-force-full-reload
option improves things.
Admin page
The admin page is only visible to users which are part of the groups configured
in the proxy.admin-groups
property. The page displays an overview of the
current running apps.
In order for the table to be responsive, some columns are hidden depending on
the screen size. All information of an app can be viewed by clicking on
the Details
button.