[arvados-workbench2] updated: 2.5.0-34-gee0b3767

git repository hosting git at public.arvados.org
Fri Feb 10 21:44:40 UTC 2023


Summary of changes:
 .licenseignore                                     |   2 +
 cypress/fixtures/files/banner.html                 |   5 +
 cypress/fixtures/files/tooltips.txt                |   3 +
 cypress/integration/banner-tooltip.spec.js         | 108 ++++++++++++++++++++
 cypress/integration/login.spec.js                  |  18 +++-
 src/common/config.ts                               |  24 +++++
 src/index.css                                      |  22 ++++
 src/index.tsx                                      |   3 +-
 src/services/auth-service/auth-service.ts          |  10 +-
 .../collection-service/collection-service.test.ts  |   4 +-
 src/services/common-service/common-service.ts      |   2 +
 src/store/auth/auth-action.ts                      |   8 +-
 src/store/auth/auth-middleware.test.ts             |   4 +-
 src/store/auth/auth-middleware.ts                  |   4 +-
 src/store/banner/banner-action.ts                  |  29 ++++++
 src/store/banner/banner-reducer.ts                 |  26 +++++
 src/store/processes/process.ts                     |   3 +
 src/store/processes/processes-actions.ts           |  38 +++++--
 .../search-results-middleware-service.ts           |  17 +++-
 src/store/store.ts                                 |   4 +-
 src/store/tooltips/tooltips-middleware.ts          |  18 ++--
 src/store/workbench/workbench-actions.ts           |  12 ++-
 src/views-components/auto-logout/auto-logout.tsx   |   2 +-
 src/views-components/baner/banner.test.tsx         |  63 ++++++++++++
 src/views-components/baner/banner.tsx              | 111 +++++++++++++++++++++
 .../main-app-bar/account-menu.test.tsx             |   2 +-
 src/views-components/main-app-bar/account-menu.tsx |   2 +-
 .../main-app-bar/notifications-menu.tsx            |  88 +++++++++++++---
 src/views/workbench/workbench.test.tsx             |   2 +
 src/views/workbench/workbench.tsx                  |   2 +
 30 files changed, 574 insertions(+), 62 deletions(-)
 create mode 100644 cypress/fixtures/files/banner.html
 create mode 100644 cypress/fixtures/files/tooltips.txt
 create mode 100644 cypress/integration/banner-tooltip.spec.js
 create mode 100644 src/store/banner/banner-action.ts
 create mode 100644 src/store/banner/banner-reducer.ts
 create mode 100644 src/views-components/baner/banner.test.tsx
 create mode 100644 src/views-components/baner/banner.tsx

       via  ee0b3767b36691938003dbb897e8e5a915233dfd (commit)
       via  b676312f840c3f12855a4392afe90b275dd25b97 (commit)
       via  49205e313604e7825b663277ceb45f0efe5fe715 (commit)
       via  e1cf48a01c6f7aca509eb4aa886bfe530cd18457 (commit)
       via  af30470573cfe6627ef39aae023f92d846f1b132 (commit)
       via  7f857c19e38816c3323ff930d13f9f981624ed8b (commit)
       via  fe6be4c404720670989f96784db9f87f8ac86b76 (commit)
       via  da1b362fc33261ace42851f6900df7b96fde819e (commit)
       via  38db7657138744ed97b924bc3396a1ec00de9be3 (commit)
       via  153c4516226560081abd11aed9dea421971595b4 (commit)
       via  8aad39537a5998cc11038e9a96f9424d46aa7443 (commit)
       via  1321d262946be46e2b6a9603294adf414a519d32 (commit)
       via  255c1853af2886e1263d101b20f68ed13d6331e4 (commit)
       via  aa48015966dd61d462f43a1a336b1700c78624aa (commit)
       via  e92b9b5472a0f32e40983b8e25e572e592691e41 (commit)
       via  6b9a82be8d59508134842191b705786efedd33bd (commit)
       via  e786d916dd77dad51daa95d948eeb1b5dc56ee94 (commit)
       via  81f173ecca4de9d012ad9219557c39a240ad8d2f (commit)
       via  68abcff0f925ea12c0d74efdafbd6c74db82ae3b (commit)
       via  ebbe5fdc661b279c5166dae75381442c2e37f1f1 (commit)
       via  be74aae5535a64c58d408d0345b0aae94758f983 (commit)
       via  2cec626e679d593d5b208a0807b391ab978e0e9d (commit)
       via  297ccba9513f02ebfa6e13ab8831eb0b195b6dc3 (commit)
       via  d3cf4aea6553f1065fc9d2312e246604653cabd8 (commit)
       via  9fdaa5832115269584ff98a5b245e96b5a649d54 (commit)
      from  070a998f625b59e09b1bedc8ee107527ad857c26 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.


commit ee0b3767b36691938003dbb897e8e5a915233dfd
Merge: 49205e31 b676312f
Author: Daniel Kutyła <daniel.kutyla at contractors.roche.com>
Date:   Fri Feb 10 18:12:47 2023 +0100

    Merge branch 'main' into 19836-new-tooltip-impl
    
    Arvados-DCO-1.1-Signed-off-by: Daniel Kutyła <daniel.kutyla at contractors.roche.com>

diff --cc .licenseignore
index 2440cc33,2440cc33..2d7deb73
--- a/.licenseignore
+++ b/.licenseignore
@@@ -16,6 -16,6 +16,8 @@@ src/lib/cwl-svg/
  tools/arvados_config.yml
  cypress/fixtures/files/5mb.bin
  cypress/fixtures/files/cat.png
++cypress/fixtures/files/banner.html
++cypress/fixtures/files/tooltips.txt
  cypress/fixtures/webdav-propfind-outputs.xml
  .yarn/releases/*
  package.json
diff --cc src/common/config.ts
index 2c7995f5,a6eabdad..9b054282
--- a/src/common/config.ts
+++ b/src/common/config.ts
@@@ -281,16 -281,16 +281,16 @@@ export const mockClusterConfigJSON = 
      WebDAVDownload: { ExternalURL: '' },
      WebShell: { ExternalURL: '' },
      Workbench: {
 -        DisableSharingURLsUI: false,
 -        ArvadosDocsite: "",
 -        FileViewersConfigURL: "",
 -        WelcomePageHTML: "",
 -        InactivePageHTML: "",
 -        SSHHelpPageHTML: "",
 -        SSHHelpHostSuffix: "",
 -        SiteName: "",
 -        IdleTimeout: "0s"
 -    }
 +      DisableSharingURLsUI: false,
 +      ArvadosDocsite: "",
 +      FileViewersConfigURL: "",
 +      WelcomePageHTML: "",
 +      InactivePageHTML: "",
 +      SSHHelpPageHTML: "",
 +      SSHHelpHostSuffix: "",
 +      SiteName: "",
-       IdleTimeout: "0s",
++      IdleTimeout: "0s"
 +    },
    },
    Workbench: {
      DisableSharingURLsUI: false,
diff --cc src/store/store.ts
index 52bb7333,4ef5e3d0..1501fd4f
--- a/src/store/store.ts
+++ b/src/store/store.ts
@@@ -74,11 -74,9 +74,10 @@@ import { ALL_PROCESSES_PANEL_ID } from 
  import { Config } from 'common/config';
  import { pluginConfig } from 'plugins';
  import { MiddlewareListReducer } from 'common/plugintypes';
- import { sidePanelReducer } from './side-panel/side-panel-reducer';
 +import { tooltipsMiddleware } from './tooltips/tooltips-middleware';
+ import { sidePanelReducer } from './side-panel/side-panel-reducer'
  import { bannerReducer } from './banner/banner-reducer';
  
- 
  declare global {
      interface Window {
          __REDUX_DEVTOOLS_EXTENSION_COMPOSE__?: typeof compose;

commit 49205e313604e7825b663277ceb45f0efe5fe715
Author: Daniel Kutyła <daniel.kutyla at contractors.roche.com>
Date:   Fri Feb 10 17:56:37 2023 +0100

    19836: Cypress tests added
    
    Arvados-DCO-1.1-Signed-off-by: Daniel Kutyła <daniel.kutyla at contractors.roche.com>

diff --git a/cypress/fixtures/files/banner.html b/cypress/fixtures/files/banner.html
new file mode 100644
index 00000000..34966bd9
--- /dev/null
+++ b/cypress/fixtures/files/banner.html
@@ -0,0 +1,5 @@
+<div>
+    <h1>Hi there</h1>
+    <h3>This is my amazing</h3>
+    <h5 style="color: red">Banner</h5>
+</div>
\ No newline at end of file
diff --git a/cypress/fixtures/files/tooltips.txt b/cypress/fixtures/files/tooltips.txt
new file mode 100644
index 00000000..c3c2162d
--- /dev/null
+++ b/cypress/fixtures/files/tooltips.txt
@@ -0,0 +1,3 @@
+{
+    "[data-cy=side-panel-tree]": "This allows you to navigate through the app"
+}
\ No newline at end of file
diff --git a/cypress/integration/banner-tooltip.spec.js b/cypress/integration/banner-tooltip.spec.js
new file mode 100644
index 00000000..f331a887
--- /dev/null
+++ b/cypress/integration/banner-tooltip.spec.js
@@ -0,0 +1,108 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+describe('Collection panel tests', function () {
+    let activeUser;
+    let adminUser;
+    let collectionUUID;
+
+    before(function () {
+        // Only set up common users once. These aren't set up as aliases because
+        // aliases are cleaned up after every test. Also it doesn't make sense
+        // to set the same users on beforeEach() over and over again, so we
+        // separate a little from Cypress' 'Best Practices' here.
+        cy.getUser('admin', 'Admin', 'User', true, true)
+            .as('adminUser').then(function () {
+                adminUser = this.adminUser;
+            }
+            );
+        cy.getUser('collectionuser1', 'Collection', 'User', false, true)
+            .as('activeUser').then(function () {
+                activeUser = this.activeUser;
+            }
+            )
+
+        cy.getAll('@adminUser')
+            .then(function([adminUser]) {
+                cy.createCollection(adminUser.token, {
+                    name: `BannerTooltipTest${Math.floor(Math.random() * 999999)}`,
+                    owner_uuid: adminUser.user.uuid,
+                }).as('bannerCollection');
+
+                cy.getAll('@bannerCollection')
+                    .then(function ([bannerCollection]) {
+
+                        collectionUUID=bannerCollection.uuid;
+        
+                        cy.loginAs(adminUser);
+        
+                        cy.goToPath(`/collections/${bannerCollection.uuid}`);
+        
+                        cy.get('[data-cy=upload-button]').click();
+        
+                        cy.fixture('files/banner.html').as('banner');
+                        cy.fixture('files/tooltips.txt').as('tooltips');
+                        
+                        cy.getAll('@banner', '@tooltips')
+                            .then(([banner, tooltips]) => {
+                                console.log(tooltips)
+                                cy.get('[data-cy=drag-and-drop]').upload(btoa(banner), 'banner.html');
+                                cy.get('[data-cy=drag-and-drop]').upload(btoa(tooltips), 'tooltips.json');
+                            });
+  
+                        cy.get('[data-cy=form-submit-btn]').click();
+                    });
+            });
+            cy.on('uncaught:exception', (err, runnable) => {console.error(err)});
+    });
+
+    beforeEach(function () {
+        cy.clearCookies();
+        cy.clearLocalStorage();
+        cy.intercept({ method: 'GET', hostname: 'localhost', url: '**/arvados/v1/config?nocache=*' }, (req) => {
+            req.reply((res) => {
+                res.body.Workbench.BannerUUID = collectionUUID;
+            });
+        });
+    });
+
+    it('should re-show the banner', () => {
+        cy.loginAs(adminUser);
+
+        cy.wait(2000);
+
+        cy.get('[data-cy=confirmation-dialog-ok-btn]').click();
+
+        cy.get('[title=Notifications]').click();
+        cy.get('li').contains('Restore Banner').click();
+
+        cy.wait(2000);
+
+        cy.get('[data-cy=confirmation-dialog-ok-btn]').should('be.visible');
+    });
+
+
+    it('should show tooltips and remove tooltips as localStorage key is present', () => {
+        cy.loginAs(adminUser);
+
+        cy.wait(2000);
+
+        cy.get('[data-cy=side-panel-tree]').then(($el) => {
+            const el = $el.get(0) //native DOM element
+            expect(el._tippy).to.exist;
+        });
+
+        cy.wait(2000);
+
+        cy.get('[data-cy=confirmation-dialog-ok-btn]').click();
+
+        cy.get('[title=Notifications]').click();
+        cy.get('li').contains('Disable tooltips').click();
+
+        cy.get('[data-cy=side-panel-tree]').then(($el) => {
+            const el = $el.get(0) //native DOM element
+            expect(el._tippy).to.be.undefined;
+        });
+    });
+});

commit e1cf48a01c6f7aca509eb4aa886bfe530cd18457
Merge: af304705 2cec626e
Author: Daniel Kutyła <daniel.kutyla at contractors.roche.com>
Date:   Fri Feb 10 16:06:04 2023 +0100

    Merge branch '18368-notification-banner' into 19836-new-tooltip-impl
    
    Arvados-DCO-1.1-Signed-off-by: Daniel Kutyła <daniel.kutyla at contractors.roche.com>

diff --cc src/common/config.ts
index 93197367,ff44e2ef..2c7995f5
--- a/src/common/config.ts
+++ b/src/common/config.ts
@@@ -28,82 -26,83 +28,94 @@@ export interface ClusterConfigJSON 
              Scheme: string
          }
      };
 -    Mail?: {
 -        SupportEmailAddress: string;
 +  Mail?: {
 +    SupportEmailAddress: string;
 +  };
 +  Services: {
 +    Controller: {
 +      ExternalURL: string;
      };
 -    Services: {
 -        Controller: {
 -            ExternalURL: string
 -        }
 -        Workbench1: {
 -            ExternalURL: string
 -        }
 -        Workbench2: {
 -            ExternalURL: string
 -        }
 -        Websocket: {
 -            ExternalURL: string
 -        }
 -        WebDAV: {
 -            ExternalURL: string
 -        },
 -        WebDAVDownload: {
 -            ExternalURL: string
 -        },
 -        WebShell: {
 -            ExternalURL: string
 -        }
 +    Workbench1: {
 +      ExternalURL: string;
 +    };
 +    Workbench2: {
 +      ExternalURL: string;
      };
+     Workbench: {
+         DisableSharingURLsUI: boolean;
+         ArvadosDocsite: string;
+         FileViewersConfigURL: string;
+         WelcomePageHTML: string;
+         InactivePageHTML: string;
+         SSHHelpPageHTML: string;
+         SSHHelpHostSuffix: string;
+         SiteName: string;
+         IdleTimeout: string;
 -        BannerUUID: string;
+     };
 -    Login: {
 -        LoginCluster: string;
 -        Google: {
 -            Enable: boolean;
 -        }
 -        LDAP: {
 -            Enable: boolean;
 -        }
 -        OpenIDConnect: {
 -            Enable: boolean;
 -        }
 -        PAM: {
 -            Enable: boolean;
 -        }
 -        SSO: {
 -            Enable: boolean;
 -        }
 -        Test: {
 -            Enable: boolean;
 -        }
 +    Websocket: {
 +      ExternalURL: string;
      };
 -    Collections: {
 -        ForwardSlashNameSubstitution: string;
 -        ManagedProperties?: {
 -            [key: string]: {
 -                Function: string,
 -                Value: string,
 -                Protected?: boolean,
 -            }
 -        },
 -        TrustAllContent: boolean
 +    WebDAV: {
 +      ExternalURL: string;
      };
 -    Volumes: {
 -        [key: string]: {
 -            StorageClasses: {
 -                [key: string]: boolean;
 -            }
 -        }
 +    WebDAVDownload: {
 +      ExternalURL: string;
 +    };
 +    WebShell: {
 +      ExternalURL: string;
 +    };
 +  };
 +  Workbench: {
 +    DisableSharingURLsUI: boolean;
 +    ArvadosDocsite: string;
 +    FileViewersConfigURL: string;
 +    WelcomePageHTML: string;
 +    InactivePageHTML: string;
 +    SSHHelpPageHTML: string;
 +    SSHHelpHostSuffix: string;
 +    SiteName: string;
 +    IdleTimeout: string;
++    BannerUUID: string;
 +  };
 +  Login: {
 +    LoginCluster: string;
 +    Google: {
 +      Enable: boolean;
 +    };
 +    LDAP: {
 +      Enable: boolean;
 +    };
 +    OpenIDConnect: {
 +      Enable: boolean;
 +    };
 +    PAM: {
 +      Enable: boolean;
 +    };
 +    SSO: {
 +      Enable: boolean;
      };
 +    Test: {
 +      Enable: boolean;
 +    };
 +  };
 +  Collections: {
 +    ForwardSlashNameSubstitution: string;
 +    ManagedProperties?: {
 +      [key: string]: {
 +        Function: string;
 +        Value: string;
 +        Protected?: boolean;
 +      };
 +    };
 +    TrustAllContent: boolean;
 +  };
 +  Volumes: {
 +    [key: string]: {
 +      StorageClasses: {
 +        [key: string]: boolean;
 +      };
 +    };
 +  };
  }
  
  export class Config {
@@@ -240,73 -219,66 +252,85 @@@ remove the entire ${varName} entry fro
  };
  
  // Maps remote cluster hosts and removes the default RemoteCluster entry
 -export const mapRemoteHosts = (clusterConfigJSON: ClusterConfigJSON, config: Config) => {
 -    config.remoteHosts = {};
 -    Object.keys(clusterConfigJSON.RemoteClusters).forEach(k => { config.remoteHosts[k] = clusterConfigJSON.RemoteClusters[k].Host; });
 -    delete config.remoteHosts["*"];
 +export const mapRemoteHosts = (
 +  clusterConfigJSON: ClusterConfigJSON,
 +  config: Config
 +) => {
 +  config.remoteHosts = {};
 +  Object.keys(clusterConfigJSON.RemoteClusters).forEach((k) => {
 +    config.remoteHosts[k] = clusterConfigJSON.RemoteClusters[k].Host;
 +  });
 +  delete config.remoteHosts['*'];
  };
  
 -export const mockClusterConfigJSON = (config: Partial<ClusterConfigJSON>): ClusterConfigJSON => ({
 -    API: {
 -        UnfreezeProjectRequiresAdmin: false,
 +export const mockClusterConfigJSON = (
 +  config: Partial<ClusterConfigJSON>
 +): ClusterConfigJSON => ({
 +  API: {
 +    UnfreezeProjectRequiresAdmin: false,
 +    MaxItemsPerResponse: 1000,
 +  },
 +  ClusterID: '',
 +  RemoteClusters: {},
 +  Services: {
 +    Controller: { ExternalURL: '' },
 +    Workbench1: { ExternalURL: '' },
 +    Workbench2: { ExternalURL: '' },
 +    Websocket: { ExternalURL: '' },
 +    WebDAV: { ExternalURL: '' },
 +    WebDAVDownload: { ExternalURL: '' },
 +    WebShell: { ExternalURL: '' },
++    Workbench: {
++      DisableSharingURLsUI: false,
++      ArvadosDocsite: "",
++      FileViewersConfigURL: "",
++      WelcomePageHTML: "",
++      InactivePageHTML: "",
++      SSHHelpPageHTML: "",
++      SSHHelpHostSuffix: "",
++      SiteName: "",
++      IdleTimeout: "0s",
+     },
 -    ClusterID: "",
 -    RemoteClusters: {},
 -    Services: {
 -        Controller: { ExternalURL: "" },
 -        Workbench1: { ExternalURL: "" },
 -        Workbench2: { ExternalURL: "" },
 -        Websocket: { ExternalURL: "" },
 -        WebDAV: { ExternalURL: "" },
 -        WebDAVDownload: { ExternalURL: "" },
 -        WebShell: { ExternalURL: "" },
 +  },
 +  Workbench: {
 +    DisableSharingURLsUI: false,
 +    ArvadosDocsite: '',
 +    FileViewersConfigURL: '',
 +    WelcomePageHTML: '',
 +    InactivePageHTML: '',
 +    SSHHelpPageHTML: '',
 +    SSHHelpHostSuffix: '',
 +    SiteName: '',
 +    IdleTimeout: '0s',
++    BannerUUID: "",
 +  },
 +  Login: {
 +    LoginCluster: '',
 +    Google: {
 +      Enable: false,
      },
 -    Workbench: {
 -        DisableSharingURLsUI: false,
 -        ArvadosDocsite: "",
 -        FileViewersConfigURL: "",
 -        WelcomePageHTML: "",
 -        InactivePageHTML: "",
 -        SSHHelpPageHTML: "",
 -        SSHHelpHostSuffix: "",
 -        SiteName: "",
 -        IdleTimeout: "0s",
 -        BannerUUID: "",
 +    LDAP: {
 +      Enable: false,
 +    },
 +    OpenIDConnect: {
 +      Enable: false,
      },
 -    Login: {
 -        LoginCluster: "",
 -        Google: {
 -            Enable: false,
 -        },
 -        LDAP: {
 -            Enable: false,
 -        },
 -        OpenIDConnect: {
 -            Enable: false,
 -        },
 -        PAM: {
 -            Enable: false,
 -        },
 -        SSO: {
 -            Enable: false,
 -        },
 -        Test: {
 -            Enable: false,
 -        },
 +    PAM: {
 +      Enable: false,
      },
 -    Collections: {
 -        ForwardSlashNameSubstitution: "",
 -        TrustAllContent: false,
 +    SSO: {
 +      Enable: false,
      },
 -    Volumes: {},
 -    ...config
 +    Test: {
 +      Enable: false,
 +    },
 +  },
 +  Collections: {
 +    ForwardSlashNameSubstitution: '',
 +    TrustAllContent: false,
 +  },
 +  Volumes: {},
 +  ...config,
  });
  
  export const mockConfig = (config: Partial<Config>): Config => ({
diff --cc src/store/store.ts
index 4213143a,899eb1cb..52bb7333
--- a/src/store/store.ts
+++ b/src/store/store.ts
@@@ -74,12 -73,11 +74,14 @@@ import { ALL_PROCESSES_PANEL_ID } from 
  import { Config } from 'common/config';
  import { pluginConfig } from 'plugins';
  import { MiddlewareListReducer } from 'common/plugintypes';
- import { sidePanelReducer } from './side-panel/side-panel-reducer'
++import { sidePanelReducer } from './side-panel/side-panel-reducer';
 +import { tooltipsMiddleware } from './tooltips/tooltips-middleware';
+ import { bannerReducer } from './banner/banner-reducer';
+ 
 +
  declare global {
      interface Window {
 -      __REDUX_DEVTOOLS_EXTENSION_COMPOSE__?: typeof compose;
 +        __REDUX_DEVTOOLS_EXTENSION_COMPOSE__?: typeof compose;
      }
  }
  
diff --cc src/store/tooltips/tooltips-middleware.ts
index 982348b4,00000000..901374d2
mode 100644,000000..100644
--- a/src/store/tooltips/tooltips-middleware.ts
+++ b/src/store/tooltips/tooltips-middleware.ts
@@@ -1,79 -1,0 +1,83 @@@
 +// Copyright (C) The Arvados Authors. All rights reserved.
 +//
 +// SPDX-License-Identifier: AGPL-3.0
 +
 +import { CollectionDirectory, CollectionFile } from "models/collection-file";
 +import { Middleware, Store } from "redux";
 +import { ServiceRepository } from "services/services";
 +import { RootState } from "store/store";
 +import tippy, { createSingleton } from 'tippy.js';
 +import 'tippy.js/dist/tippy.css';
 +
 +let running = false;
 +let tooltipsContents = null;
 +let tooltipsFetchFailed = false;
- const TOOLTIP_LOCAL_STORAGE_KEY = "TOOLTIP_LOCAL_STORAGE_KEY";
++export const TOOLTIP_LOCAL_STORAGE_KEY = "TOOLTIP_LOCAL_STORAGE_KEY";
++
++const tippySingleton = createSingleton([], {delay: 10});
 +
 +export const tooltipsMiddleware = (services: ServiceRepository): Middleware => (store: Store) => next => action => {
 +    const state: RootState = store.getState();
-     const result = localStorage.getItem(TOOLTIP_LOCAL_STORAGE_KEY);
-     const { BannerURL } = (state.auth.config.clusterConfig.Workbench as any);
++    const hideTooltip = localStorage.getItem(TOOLTIP_LOCAL_STORAGE_KEY);
++    const { BannerUUID } = (state.auth.config.clusterConfig.Workbench as any);
 +
-     let bannerUUID = !!BannerURL ? BannerURL : 'tordo-4zz18-1buneu6sb8zxiti';
++    const bannerUUID = BannerUUID || 'tordo-4zz18-1buneu6sb8zxiti';
 +
-     if (bannerUUID && !tooltipsContents && !result && !tooltipsFetchFailed && !running) {
++    if (bannerUUID && !tooltipsContents && !hideTooltip && !tooltipsFetchFailed && !running) {
 +        running = true;
 +        fetchTooltips(services, bannerUUID);
-     } else if (tooltipsContents && !result && !tooltipsFetchFailed) {
++    } else if (tooltipsContents && !hideTooltip && !tooltipsFetchFailed) {
 +        applyTooltips();
 +    }
 +
 +    return next(action);
 +};
 +
 +const fetchTooltips = (services, bannerUUID) => {
 +    services.collectionService.files(bannerUUID)
 +        .then(results => {
 +            const tooltipsFile: CollectionDirectory | CollectionFile | undefined = results.find(({ name }) => name === 'tooltips.json');
 +
 +            if (tooltipsFile) {
 +                running = true;
 +                services.collectionService.getFileContents(tooltipsFile as CollectionFile)
 +                    .then(data => {
 +                        tooltipsContents = JSON.parse(data);
 +                        applyTooltips();
 +                    })
 +                    .catch(() => {})
 +                    .finally(() => {
 +                        running = false;
 +                    });
 +            }  else {
 +                tooltipsFetchFailed = true;
 +            }
 +        })
 +        .catch(() => {})
 +        .finally(() => {
 +            running = false;
 +        });
 +};
 +
 +const applyTooltips = () => {
 +    const tippyInstances: any[] = Object.keys(tooltipsContents as any)
 +        .map((key) => {
 +            const content = (tooltipsContents as any)[key]
 +            const element = document.querySelector(key);
 +
 +            if (element) {
 +                const hasTippyAttatched = !!(element as any)._tippy;
 +
 +                if (!hasTippyAttatched && tooltipsContents) {
 +                    return tippy(element as any, { content });
 +                }
 +            }
 +
 +            return null;
 +        })
 +        .filter(data => !!data);
 +
-         createSingleton(tippyInstances, {delay: 10});
++    if (tippyInstances.length > 0) {
++        tippySingleton.setInstances(tippyInstances);
++    }
 +};
diff --cc src/views-components/main-app-bar/notifications-menu.tsx
index e27bdad5,30a5756f..ca97a612
--- a/src/views-components/main-app-bar/notifications-menu.tsx
+++ b/src/views-components/main-app-bar/notifications-menu.tsx
@@@ -3,21 -3,59 +3,77 @@@
  // SPDX-License-Identifier: AGPL-3.0
  
  import React from "react";
- import { Badge, MenuItem } from '@material-ui/core';
+ import { Dispatch } from "redux";
+ import { connect } from "react-redux";
+ import { Badge, MenuItem } from "@material-ui/core";
  import { DropdownMenu } from "components/dropdown-menu/dropdown-menu";
- import { NotificationIcon } from 'components/icon/icon';
- 
- export const NotificationsMenu = 
-     () =>
-         <DropdownMenu
-             icon={
-                 <Badge
-                     badgeContent={0}
-                     color="primary">
-                     <NotificationIcon />
-                 </Badge>}
-             id="account-menu"
-             title="Notifications">
-             <MenuItem>You are up to date</MenuItem>
-         </DropdownMenu>;
+ import { NotificationIcon } from "components/icon/icon";
+ import bannerActions from "store/banner/banner-action";
+ import { BANNER_LOCAL_STORAGE_KEY } from "views-components/baner/banner";
+ import { RootState } from "store/store";
++import { TOOLTIP_LOCAL_STORAGE_KEY } from "store/tooltips/tooltips-middleware";
++import { useCallback } from "react";
  
+ const mapStateToProps = (state: RootState): NotificationsMenuProps => ({
+     isOpen: state.banner.isOpen,
+     bannerUUID: state.auth.config.clusterConfig.Workbench.BannerUUID,
+ });
+ 
+ const mapDispatchToProps = (dispatch: Dispatch) => ({
+     openBanner: () => dispatch<any>(bannerActions.openBanner()),
+ });
+ 
+ type NotificationsMenuProps = {
+     isOpen: boolean;
+     bannerUUID?: string;
+ }
+ 
+ type NotificationsMenuComponentProps = NotificationsMenuProps & {
+     openBanner: any;
+ }
+ 
+ export const NotificationsMenuComponent = (props: NotificationsMenuComponentProps) => {
+     const { isOpen, openBanner } = props;
 -    const result = localStorage.getItem(BANNER_LOCAL_STORAGE_KEY);
++    const bannerResult = localStorage.getItem(BANNER_LOCAL_STORAGE_KEY);
++    const tooltipResult = localStorage.getItem(TOOLTIP_LOCAL_STORAGE_KEY);
+     const menuItems: any[] = [];
+ 
 -    if (!isOpen && result) {
++    if (!isOpen && bannerResult) {
+         menuItems.push(<MenuItem><span onClick={openBanner}>Restore Banner</span></MenuItem>);
+     }
+ 
++    const toggleTooltips = useCallback(() => {
++        if (tooltipResult) {
++            localStorage.removeItem(TOOLTIP_LOCAL_STORAGE_KEY);
++        } else {
++            localStorage.setItem(TOOLTIP_LOCAL_STORAGE_KEY, 'true');
++        }
++        window.location.reload();
++    }, [tooltipResult]);
++
++    if (tooltipResult) {
++        menuItems.push(<MenuItem><span onClick={toggleTooltips}>Enable tooltips</span></MenuItem>);
++    } else {
++        menuItems.push(<MenuItem><span onClick={toggleTooltips}>Disable tooltips</span></MenuItem>);
++    }
++
+     if (menuItems.length === 0) {
+         menuItems.push(<MenuItem>You are up to date</MenuItem>);
+     }
+ 
+     return (<DropdownMenu
+         icon={
+             <Badge
+                 badgeContent={0}
+                 color="primary">
+                 <NotificationIcon />
+             </Badge>}
+         id="account-menu"
+         title="Notifications">
+         {
 -            menuItems.map(item => item)
++            menuItems.map((item, i) => <div key={i}>{item}</div>)
+         }
+     </DropdownMenu>);
+ }
+ 
+ export const NotificationsMenu = connect(mapStateToProps, mapDispatchToProps)(NotificationsMenuComponent);
diff --cc src/views/workbench/workbench.tsx
index 87f004b3,b6ce07ae..7103efd1
--- a/src/views/workbench/workbench.tsx
+++ b/src/views/workbench/workbench.tsx
@@@ -99,7 -99,7 +99,8 @@@ import { RestoreCollectionVersionDialo
  import { WebDavS3InfoDialog } from 'views-components/webdav-s3-dialog/webdav-s3-dialog';
  import { pluginConfig } from 'plugins';
  import { ElementListReducer } from 'common/plugintypes';
 +import { COLLAPSE_ICON_SIZE } from 'views-components/side-panel-toggle/side-panel-toggle'
+ import { Banner } from 'views-components/baner/banner';
  
  type CssRules = 'root' | 'container' | 'splitter' | 'asidePanel' | 'contentWrapper' | 'content';
  
@@@ -293,6 -271,7 +294,7 @@@ export const WorkbenchPanel 
              <VirtualMachineAttributesDialog />
              <FedLogin />
              <WebDavS3InfoDialog />
+             <Banner />
              {React.createElement(React.Fragment, null, pluginConfig.dialogs)}
 -        </Grid>
 +        </Grid>}
      );

commit af30470573cfe6627ef39aae023f92d846f1b132
Merge: 070a998f 7f857c19
Author: Daniel Kutyła <daniel.kutyla at contractors.roche.com>
Date:   Sun Feb 5 00:34:11 2023 +0100

    Merge remote-tracking branch 'origin/main' into 19836-new-tooltip-impl
    
    Arvados-DCO-1.1-Signed-off-by: Daniel Kutyła <daniel.kutyla at contractors.roche.com>


-----------------------------------------------------------------------


hooks/post-receive
-- 




More information about the arvados-commits mailing list