Skip to content

Commit

Permalink
Release 21.10.0 (#72).
Browse files Browse the repository at this point in the history
  • Loading branch information
yakutovicha authored Sep 27, 2021
2 parents 9961f74 + 84bed16 commit d3940a2
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 30 deletions.
30 changes: 21 additions & 9 deletions home/app_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import ipywidgets as ipw
import traitlets
from aiidalab.app import AppRemoteUpdateStatus as AppStatus
from aiidalab.app import AppVersion
from jinja2 import Template
from packaging.version import parse
Expand Down Expand Up @@ -240,6 +241,10 @@ def _refresh_widget_state(self, _=None):
installed = self.app.is_installed()
installed_version = self.app.installed_version
compatible = len(self.app.available_versions) > 0
registered = self.app.remote_update_status is not AppStatus.NOT_REGISTERED
cannot_reach_registry = (
self.app.remote_update_status is AppStatus.CANNOT_REACH_REGISTRY
)
busy = self.app.busy
detached = self.app.detached
available_versions = self.app.available_versions
Expand All @@ -248,7 +253,9 @@ def _refresh_widget_state(self, _=None):
blocked_install = (
detached or not compatible
) and not self.blocked_ignore.value
blocked_uninstall = detached and not self.blocked_ignore.value
blocked_uninstall = (
detached or not registered or cannot_reach_registry
) and not self.blocked_ignore.value

# Check app compatibility and show banner if not compatible.
self.compatibility_warning.layout.visibility = (
Expand All @@ -261,11 +268,9 @@ def _refresh_widget_state(self, _=None):
# These messages and icons are only shown if needed.
warn_or_ban_icon = "warning" if override else "ban"
if override:
tooltip_danger = (
"Operation will lead to potential loss of local modifications!"
)
tooltip_danger = "Operation will lead to potential loss of local data!"
else:
tooltip_danger = "Operation blocked due to local modifications."
tooltip_danger = "Operation blocked due to potential data loss."
tooltip_incompatible = "The app is not supported for this environment."

# Determine whether we can install, updated, and uninstall.
Expand All @@ -279,7 +284,10 @@ def _refresh_widget_state(self, _=None):
) or not installed
can_uninstall = installed
try:
can_update = self.app.updates_available and installed
can_update = (
self.app.remote_update_status is AppStatus.UPDATE_AVAILABLE
and installed
)
except RuntimeError:
can_update = None

Expand Down Expand Up @@ -362,10 +370,14 @@ def _refresh_widget_state(self, _=None):
)

# Indicate whether there are local modifications and present option for user override.
if detached:
if cannot_reach_registry:
self.issue_indicator.value = f'<i class="fa fa-{warn_or_ban_icon}"></i> Unable to reach the registry server.'
elif not registered:
self.issue_indicator.value = f'<i class="fa fa-{warn_or_ban_icon}"></i> The app is not registered.'
elif detached:
self.issue_indicator.value = (
f'<i class="fa fa-{warn_or_ban_icon}"></i> The app is modified or the installed version '
"is not on the specified release line."
f'<i class="fa fa-{warn_or_ban_icon}"></i> The app has local modifications or was checked out '
"to an unknown version."
)
elif not compatible:
self.issue_indicator.value = f'<i class="fa fa-{warn_or_ban_icon}"></i> The app is not supported for this environment.'
Expand Down
10 changes: 8 additions & 2 deletions home/app_store.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
"""AiiDAlab app store."""
import logging

import ipywidgets as ipw
from aiidalab.app import AiidaLabApp
Expand All @@ -9,13 +10,18 @@

from home.app_manager import AppManagerWidget

logger = logging.getLogger(__name__)


class AiidaLabAppStore(ipw.HBox):
"""Class to manage AiiDAlab app store."""

def __init__(self):
# TODO: Improve fallback implementation!
self.index = load_app_registry_index() or dict(apps=[], categories=[])
try:
self.index = load_app_registry_index()
except RuntimeError as error:
logger.warning(error)
self.index = dict(apps=[], categories=[])
self.output = ipw.Output()

# Apps per page.
Expand Down
2 changes: 1 addition & 1 deletion home/start_page.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ def __init__(self, app, allow_move=False, allow_manage=True):

if allow_manage:
app_status_info = AppStatusInfoWidget()
for trait in ("detached", "compatible", "updates_available"):
for trait in ("detached", "compatible", "remote_update_status"):
ipw.dlink((app, trait), (app_status_info, trait))
app_status_info.layout.margin = "0px 0px 0px 800px"
header_items.append(app_status_info)
Expand Down
2 changes: 2 additions & 0 deletions home/themes.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ class IconSetDefault:
CHAIN_BROKEN = '<i class="fa fa-chain-broken" aria-hidden="true"></i>'
LOADING = '<i class="fa fa-hourglass" aria-hidden="true"></i>'
ARROW_CIRCLE_UP = '<i class="fa fa-arrow-circle-up" aria-hidden="true"></i>'
FOLDER = '<i class="fa fa-folder-o" aria-hidden="true"></i>'

# App states (general)
APP_DETACHED = CHAIN_BROKEN
APP_INCOMPATIBLE = TIMES_CIRCLE
APP_VERSION_INCOMPATIBLE = WARNING
APP_NOT_REGISTERED = FOLDER

# App states (updates)
APP_NO_UPDATE_AVAILABLE = CHECK
Expand Down
36 changes: 18 additions & 18 deletions home/widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

import ipywidgets as ipw
import traitlets
from aiidalab.app import AppRemoteUpdateStatus as AppStatus
from aiidalab.config import AIIDALAB_REGISTRY

from .themes import ThemeDefault as Theme

Expand Down Expand Up @@ -74,26 +76,23 @@ class AppStatusInfoWidget(ipw.HTML):

detached = traitlets.Bool(allow_none=True)
compatible = traitlets.Bool(allow_none=True)
updates_available = traitlets.Bool(allow_none=True)
remote_update_status = traitlets.UseEnum(AppStatus)

MESSAGE_INIT = f"<div>{Theme.ICONS.LOADING} Loading...</div>"

TOOLTIP_DETACHED = (
TOOLTIP_APP_DETACHED = (
"The app is in a detached state - likely due to local modifications - "
"which means the ability to manage the app via the AiiDAlab interface is reduced."
)

MESSAGE_DETACHED = (
f'<div title="{TOOLTIP_DETACHED}"><font color="{Theme.COLORS.GRAY}">'
f"{Theme.ICONS.APP_DETACHED} Modified</font></div>"
)

TOOLTIP_APP_INCOMPATIBLE = (
"None of the available app versions are compatible with this AiiDAlab environment. "
"You can continue using this app, but be advised that you might encounter "
"compatibility issues."
)

TOOLTIP_APP_NOT_REGISTERED = "This app is not registered."

MESSAGE_APP_INCOMPATIBLE = (
f'<div title="{TOOLTIP_APP_INCOMPATIBLE}"><font color="{Theme.COLORS.DANGER}">'
f"{Theme.ICONS.APP_INCOMPATIBLE} App incompatible</font></div>"
Expand All @@ -106,31 +105,32 @@ class AppStatusInfoWidget(ipw.HTML):
)

MESSAGES_UPDATES = {
None: '<div title="Encountered unknown problem while trying to determine whether '
"updates are available for this app.>"
f'<font color="{Theme.COLORS.WARNING}">{Theme.ICONS.APP_UPDATE_AVAILABLE_UNKNOWN} '
"Unable to determine availability of updates.</font></div>",
True: '<div title="Click on &quot;Manage app&quot; to install a newer version of this app.">'
AppStatus.CANNOT_REACH_REGISTRY: f'<div title="Unable to reach the registry server ({AIIDALAB_REGISTRY}).">'
f'<font color="{Theme.COLORS.GRAY}">{Theme.ICONS.APP_UPDATE_AVAILABLE_UNKNOWN} '
"Cannot reach server.</font></div>",
AppStatus.UPDATE_AVAILABLE: '<div title="Click on &quot;Manage app&quot; to install a newer version of this app.">'
f'<font color="{Theme.COLORS.NOTIFY}">{Theme.ICONS.APP_UPDATE_AVAILABLE} Update available</font></div>',
False: '<div title="The currently installed version of this app is the latest available version.">'
AppStatus.UP_TO_DATE: '<div title="The currently installed version of this app is the latest available version.">'
f'<font color="{Theme.COLORS.CHECK}">{Theme.ICONS.APP_NO_UPDATE_AVAILABLE} Latest version</font></div>',
AppStatus.DETACHED: f'<div title="{TOOLTIP_APP_DETACHED}"><font color="{Theme.COLORS.GRAY}">'
f"{Theme.ICONS.APP_DETACHED} Modified</font></div>",
AppStatus.NOT_REGISTERED: f'<div title="{TOOLTIP_APP_NOT_REGISTERED}"><font color="{Theme.COLORS.GRAY}">'
f"{Theme.ICONS.APP_NOT_REGISTERED} Not registered</font></div>",
}

def __init__(self, value=None, **kwargs):
if value is None:
value = self.MESSAGE_INIT
super().__init__(value=value, **kwargs)
self.observe(
self._refresh, names=["detached", "compatible", "updates_available"]
self._refresh, names=["detached", "compatible", "remote_update_status"]
)

def _refresh(self, _=None):
if self.detached is True:
self.value = self.MESSAGE_DETACHED
elif self.compatible is False:
if self.compatible is False:
self.value = self.MESSAGE_APP_INCOMPATIBLE
else:
self.value = self.MESSAGES_UPDATES[self.updates_available]
self.value = self.MESSAGES_UPDATES[self.remote_update_status]


class Spinner(ipw.HTML):
Expand Down

0 comments on commit d3940a2

Please sign in to comment.