@glue42/launchpad-ui-react
TypeScript icon, indicating that this package has built-in type declarations

0.5.8 • Public • Published

Glue42 Launchpad and Global Search · example workflow PRs Welcome

This @glue42/launchpad-react-ui component library contains Glue42 enabled React components that let you create a Glue42 toolbar. It exports two main components: <Launchpad/> and <GlobalSearch/>. The primary purpose of a Glue42 toolbar is managing the applications, workspaces and various Glue42 Enterprise settings available to the user. In addition to that, you can create an application that implements the Search Provider protocol and be able to send your own custom search results to the <GlobalSearch/> component, which can do whatever you program them to do, when a user clicks on them!

Currently @glue42/launchpad-react-ui components only work with Glue42 Enterprise. Glue Desktop for Enterprise should already be running in order for the toolbar to be usable.

Quick Start


Getting started with the default settings

You need to a create a React application using create-react-app cli tool. Run the following command in a directory of your choice:

npx create-react-app awesome-glue-toolbar

The toolbar is a Glue Desktop Application that is configured to run on http://localhost:3008 by default. The <Launchpad /> component is served on the URL path /launchpad and the <GlobalSearch /> component is served on the URL path /global-search. You must instruct create-react-app to launch the awesome-glue-toolbar application on port 3008. You can do that by creating a .env file at the root of the project directory with the following text:

PORT=3008
SKIP_PREFLIGHT_CHECK=true

After setting up on which port the application should run on, install the following dependencies:

npm i -S @glue42/launchpad-ui-react @glue42/react-hooks react-router-dom

The toolbar expects that the Glue object is initialized using the @glue42/react-hooks library. You need to import the <GlueProvider /> component from it. It uses the React Context API to pass the initialized Glue object down the React tree. You need to pass the following object { appManager: 'full', layouts: 'full' to the config prop of the <GlueProvider />, because they are required for proper operation. Go to the index.js file of the awesome-glue-toolbar project and add the following code:

import React from 'react';
import ReactDOM from 'react-dom';
import '@glue42/launchpad-ui-react/dist/vnext.css';
import Glue from '@glue42/desktop';
import { GlueProvider } from '@glue42/react-hooks';

import { LaunchPad, GlobalSearch } from '@glue42/launchpad-ui-react';

ReactDOM.render(
  <GlueProvider config={{ appManager: 'full', layouts: 'full' }} glueFactory={Glue}>
    <BrowserRouter>
      <Routes>
        <Route path="/launchpad" element={<LaunchPad/>} />
        <Route path="/global-search" element={<GlobalSearch placeholder="Search..."/>} />
      </Routes>
    </BrowserRouter>
  </GlueProvider>,
  document.getElementById('root')
);

and run the following command:

npm start

You should now be able to open Launchpad when you press the Wnd + G keyboard combination and Global Search when you press the Ctrl + Space keyboard combination.

Launchpad Features Overview


Displaying all applications and layouts of type Global and Workspace in <Launchpad/> which are not hidden

Upon starting the application that uses the <Launchpad/> component, it will load all of the Glue42 applications and layouts that are avaliable to the current user.

Grouping applications and layouts by folders

Folder names can be specified in the configuration files of different layouts and applications which Launchpad will automatically detect and group the applications and layouts by their corresponding folders. Layouts and applications without folders will be grouped at the bottom of the list

Providing a custom sort order for each application

Applications and layouts can be rearranged by setting the userProperties.appManagerOrder in each applications config. By default each application has a sortOrder of 1000. When two applications have the same sort order, they will be ordered lexicographically. Folders inherit the minimum of the sort orders of the child applications.

Searching by application/layout name

At the top there is a search bar which allows for searching applications and layouts by name.

Constrain the search to layout names only

When you click on the Show layouts only button next to the search bar, <Launchpad/> will show you only the layouts whose name includes the search term.

Marking applications and layouts as favorites

You can mark every application and layout in the list as favorite by clicking on the star icon next to it's name, so that you can have easy access to it in the future. Clicking on the star icon again will unmark the given application as favorite.

Track recently used applications and layouts

Every time you click on applications and layouts they will be marked as recently used.

Use the context-sensitive menu

You can right click on items in the list of applications and layouts, on the favorite and recently used applications and layouts as well, which will bring up a context-sensitive menu. You can mark an application or layout as favorite, unmark it, and you can even delete layouts using this menu, when you click on a layout

Saving the current layout

When you have a few open applications, you can save them as a layout by pressing the keyboard combination Ctrl + S while the Launchpad part of the toolbar is open. This will bring a dialog which will prompt you to enter the layout's name and then save it when you click on the save button. If you enter a layout's name which already exists, the dialog will offer to replace the existing layout. You can close the dialog ot any time by clicking on the Cancel button, by clicking on the close button at the top of the window, or by pressing the Escape key.

See notifications and open the notifications bar

You have a bell icon at the top left corner of the Launchpad window which shows the current number of unread notifications. By clicking on it, you can view them in the notifications bar, which will be opened.

Hamburger menu

Next to the notifications bell, there is a hamburger menu which contains useful information and a couple of features. The information included is:

  • Glue42 Version
  • Current user
  • Gateway URL
  • Environment and region

The functionality provided by the hamburger menu is:

  • Save Layout - which will open the previously mentioned layout dialog
  • Launch Global Search - which will open the Global Search window
  • Switch Themes
  • Feedback - which will open the Glue42 Feedback form
  • About - which will open the Glue42 About form
  • Restart
  • Shutdown

Global Search Features Overview


Loading results from Search Providers

Global Search will make a request to all Glue 42 Search Providers when you start typing in the search box. All the results will be displayed in a list at the bottom of the search box.

Mark result as favorite

You can mark the returned results as favorites by clicking on the star icon next to their name. They will be presented in Launchpad.

Mark results as recently used

Whenever a search result is clicked or opened in any way through Global Search, it will be marked as recently used in Launchpad.

Provide your custom search results

You can create your own Search Provider! Global Search follows a protocol when making requests to and getting results from search providers. The protocol uses the Glue42 Interop API as a communication medium. If you properly implement the given protocol and supply data in the appropriate format, you can send results to Global Search whenever someone starts searching for something! The protocol is not limited to just returning items as search results. You can specify an action that should happen when someone clicks on the result that has been returned by your search provider! The only limitation is that the action must happen through the Glue42 Interop API.

Customizations


LaunchPad

Hiding the favorite and recent applications panel

You can toggle the showFavoritesAndRecentsPanel flag to show/hide the panel with the favorite and recent applications:

<LaunchPad
  showFavoritesAndRecentsPanel={false}
/>

The above example will hide the favorites and recents panel.

Hiding the save layout icon

You can toggle the showSaveButton flag to show/hide the save button at the top of the application:

<LaunchPad
  showSaveButton={false}
/>

The above example will hide the save layout button.

Hiding the notifications button

You can toggle the showNotificationsButton button to show/hide the notifications button at the top of the application:

<LaunchPad
  showNotificationsButton={false}
/>

The above example will hide the notifications button.

The following props are implemented using React's render prop pattern. Refer to the documentation for a thorough explanation of what it is and how it works.

Adding custom/reordering items in the hamburger menu

You can reorder the items in the hamburger menu and you can even add you own custom elements using <LaunchPad/>'s hamburgerMenuItems props.

import { AboutMenuItem } from '@glue42/launchpad-ui-react';

<LaunchPad
  components={{
    hamburgerMenuItems: [
      AboutMenuItem
    ]
  }}
/>

The code snippet above will remove all items from the hamburger menu and leave only the AboutMenuItem, which when clicked gives information about the application. All snippets can be imported from the @glue42/launchpad-ui-react library. Here is a list of all the menu items that you can add to the hamburgerMenuItems array prop:

  • AboutMenuItem - gives information about the application when clicked on
  • SaveLayoutMenuItem - opens the save layout dialog which allows you the save a group of applications as a single layout
  • LaunchGlobalSearchMenuItem - open the Global Search application
  • SwitchThemesMenuItem - switches the themes of the application
  • FeedbackMenuItem - allows the user to send feedback about the application when clicked on
  • DividerMenuItem - inserts a dividing line between to adjacent menu items
  • SystemInfoHeader - the system information header item
  • SystemInfoVersion - shows the system version
  • SystemInfoUser - shows the current user
  • SystemInfoGatewayURL - shows the Gateway URL
  • SystemInfoEnvRegion - shows the environment and the region of the application
  • RestartAppMenuItem - shows the restart application button
  • ShutdownAppMenuItem - shows the shutdown application button

You can add your own custom menu items like so:

import { FeedbackMenuItem } from '@glue42/launchpad-ui-react';

<LaunchPad 
  components={{
    hamburgerMenuItems: [
      FeedbackMenuItem,
      () => <p>This is my custom hamburger menu item component</p>
    ]
  }}
/>

This will show the send feedback button and your own custom hamburger menu component below it. Note: In order to have a properly formatted menu items you need to use the <DropdownItem/> component which we export. If you do not wrap your menu item JSX with this component, you are responsible for the proper styling of your custom menu item.

Here is how to insert a custom menu item component that is styled like the existing build-in menu item components:

import { DropdownItem } from '@glue42/launchpad-ui-react';

<LaunchPad 
  components={{
    hamburgerMenuItems: [
      () => <DropdownItem>This is FIRST custom hamburger menu item component</DropdownItem>,
      () => <DropdownItem>This is SECOND custom hamburger menu item component</DropdownItem>
    ]
  }}
/>

This will display your custom menu items with styling that makes them visually appear like the built-in menu items.

Adding a custom restart/shutdown dialog content

You can create custom dialog content for when the user clicks the shutdown or restart button to exit the application. The following examples will show how to create such content:

<LaunchPad 
  components={{
    renderShutdownDialog: ({ closeDialog }) => {
      return (
        <div>
          <p>Do you want to shutdown LaunchPad?</p>
          <button onClick={() => glue.appManager.exit({showDialogs: false})}>Yes</button>
          <button onClick={closeDialog}>No</button>
        </div>
      )
    }
  }}
/>
<LaunchPad 
  components={{
    renderRestartDialog: ({ closeDialog }) => {
      return (
        <div>
          <p>Do you want to restart LaunchPad?</p>
          <button onClick={() => glue.appManager.restart()}>Yes</button>
          <button onClick={closeDialog}>No</button>
        </div>
      )
    }
  }}
/>

Adding a custom logo

You can add your own custom logo that will be shown on the upper right corner of the UI. You can change the logo by using the logo property that is part of the components prop on the <LaunchPad /> component like in the following example:

<LaunchPad
  components={{
    logo={() => <img src={/my/awesome/company/logo}>}
  }}
/>

Adding a custom list item renderer

Additionally, you can customize how the list items on the left (the ones that show applications and layouts) are rendered by passing your own renderer to the <LaunchPad /> component like so:

<LaunchPad
  components={{
    renderApplicationsAndLayoutsItem={props => <p>This is my custom list item!</p>}
  }}
/>

The custom component that you pass will receive the following properties from the <LaunchPad /> components:

  • app - this is the internal representation of Glue42 Applications and Glue42 Layouts (global and workspace) that LaunchPad uses. It is the current app of the current row that is being rendered.
  • focusOrder - this is a number that represents the position at which the current list item should receive focus. It is used internally by focus manager of <LaunchPad />. In order for your renderer to participate in focus switching, you must register it with the FocusArea React context. Otherwise, your renderer will work, but it will not receive focus. Example given below:
  • level - this is a number that represents the nesting level of the currently rendered application. The levels start from 0, which means that the application is not in any folder, and increases by 1 for each nesting level. Currently we can't nest folders but this will probably be added in the near future.
    const appRef = useRef<HTMLElement | null>(null);

    const { addFocusElement } = useContext(FocusAreaContext);

    useEffect(() => {
        if (addFocusElement && appRef && (focusOrder !== undefined)) {
            addFocusElement({ focusOrder, elementRef: appRef });
        }
        return;
    }, [addFocusElement, appRef, focusOrder]);

    return (<div ref={appRef}>My custom HTML</div>)
  • setShowcaseApp - you can use this function to send the application to be showcased the the user hovers over it, clicks it, moves focus to it, etc. You can use it likes so:
<div
  onMouseOver={() => setShowcaseApp(app)}
  onMouseLeave={() => setShowcaseApp(undefined)}
  ...

This will display the application in the special showcase component inside of <LaunchPad /> when the user hovers over your custom list item renderer and will clear the application from the showcase component when the user's mouse leaves the div element.

  • markRecentlyUsed - you can use this function to mark the current application being rendered as favorite. Here is an example of marking the application as recently used when the user click's on the application:
<div
  onClick={() => markRecentlyUsed(app)}
  • markFavorite - this function can be used to mark the application as favorite. This will cause <LaunchPad /> to display the application in the Favorites grid to the right of the list Example:
<div
  onClick={() => markFavorite(app)}
  • unmarkFavorite - this function can be used to remove the application from favorites, which will cause <LaunchPad /> to remove the application from the favorites grid to the right of the list items. This example will unmark the application as favorite whenever the user right clicks on it:
<div
  onContextMenu={() => unmarkFavorite(app)}
  • syncFavWithLP - this function is used to synchronize the favorite applications with <GlobalSearch />. Because <LaunchPad /> and <GlobalSearch /> are used as separate applications, internally they use the Glue42 Interop API to understand which applications have been marked as recent or favorite. Note: Every application has a 'persistable' form. You get this from when you call the getPersistableForm() method. You must send the persistable form and from each application or the Glue42 Interop API will throw an error!. Example usage:
<div
  onKeyDown={e => {
    if (e.key === "Enter") {
      markFavorite(app);
      // ATTENTION: SEND THE PERSISTABLE FORM
      syncFavWithLP(app.getPersistableForm());
    }
  }}
  • syncUnfavWithLP - use this function to synchronize and application that was unmarked as favorite. Note: Send the persistable form of the application, which you can get using the getPersistableForm() method of the application. Example:
<div
  onKeyDown={e => {
    if (e.key === "Enter") {
      unmarkFavorite(app);
      // ATTENTION: SEND THE PERSISTABLE FORM
      syncUnfavWithLP(app.getPersistableForm());
    }
  }}

The above examples will mark/unmark the application as favorite in <LaunchPad /> and synchronize the change with <GlobalSearch />.

The next three methods work with the LaunchPad's context menu. You pass an application to it and the coordinates at which you want the context menu to appear at.

  • setIsContextMenuOpen - tell <LaunchPad /> to open the context menu.

  • setContextMenuCoordinates - the coordinates at which to render the context menu (usually the current mouse x and y coordinates).

  • setAppForContextMenu - the application which the context menu analyses and display different options based on the state of the application (hence the name "context" menu).

Example usage of all of the above mentioned methods:

<div
  onContextMenu={e => {
    setAppForContextMenu(app);
    setContextMenuCoordinates({ x: e.pageX, y: e.pageY });
    setIsContextMenuOpen(true);
  }}

This example will open the context menu with the current application selected at the user's current mouse coordinates, when the user clicks on the list item with the right mouse button.

Adding a custom renderer for applications marked as favorite

Additionally, you can customize how the favorite items are being rendered on the right (the ones that show applications and layouts) are rendered by passing your own renderer to the <LaunchPad /> component like so:

<LaunchPad
  components={{
    renderFavoriteItem={props => <p>This is my custom favorite item!</p>}
  }}
/>
  • app - this is the internal representation of Glue42 Applications and Glue42 Layouts (global and workspace) that LaunchPad uses. It is the current app of the current row that is being rendered.
  • focusOrder - this is a number that represents the position at which the current list item should receive focus. It is used internally by focus manager of <LaunchPad />. In order for your renderer to participate in focus switching, you must register it with the FocusArea React context. Otherwise, your renderer will work, but it will not receive focus. Example given below:
    const appRef = useRef<HTMLElement | null>(null);

    const { addFocusElement } = useContext(FocusAreaContext);

    useEffect(() => {
        if (addFocusElement && appRef && (focusOrder !== undefined)) {
            addFocusElement({ focusOrder, elementRef: appRef });
        }
        return;
    }, [addFocusElement, appRef, focusOrder]);

    return (<div ref={appRef}>My custom HTML</div>)
  • setShowcaseApp - you can use this function to send the application to be showcased the the user hovers over it, clicks it, moves focus to it, etc. You can use it likes so:
<div
  onMouseOver={() => setShowcaseApp(app)}
  onMouseLeave={() => setShowcaseApp(undefined)}
  ...

This will display the application in the special showcase component inside of <LaunchPad /> when the user hovers over your custom list item renderer and will clear the application from the showcase component when the user's mouse leaves the div element.

  • markRecentlyUsed - you can use this function to mark the current application being rendered as favorite. Here is an example of marking the application as recently used when the user click's on the application:
<div
  onClick={() => markRecentlyUsed(app)}

The next three methods work with the LaunchPad's context menu. You pass an application to it and the coordinates at which you want the context menu to appear at.

  • setIsContextMenuOpen - tell <LaunchPad /> to open the context menu.

  • setContextMenuCoordinates - the coordinates at which to render the context menu (usually the current mouse x and y coordinates).

  • setAppForContextMenu - the application which the context menu analyses and display different options based on the state of the application (hence the name "context" menu).

Example usage of all of the above mentioned methods:

<div
  onContextMenu={e => {
    setAppForContextMenu(app);
    setContextMenuCoordinates({ x: e.pageX, y: e.pageY });
    setIsContextMenuOpen(true);
  }}

This example will open the context menu with the current application selected at the user's current mouse coordinates, when the user clicks on the list item with the right mouse button.

Adding a custom renderer for applications marked as recent

Additionally, you can customize how the recent items are being rendered on the right (the ones that show applications and layouts) are rendered by passing your own renderer to the <LaunchPad /> component like so:

<LaunchPad
  components={{
    renderRecentItem={props => <p>This is my recent item!</p>}
  }}
/>
  • app - this is the internal representation of Glue42 Applications and Glue42 Layouts (global and workspace) that LaunchPad uses. It is the current app of the current row that is being rendered.
  • focusOrder - this is a number that represents the position at which the current list item should receive focus. It is used internally by focus manager of <LaunchPad />. In order for your renderer to participate in focus switching, you must register it with the FocusArea React context. Otherwise, your renderer will work, but it will not receive focus. Example given below:
    const appRef = useRef<HTMLElement | null>(null);

    const { addFocusElement } = useContext(FocusAreaContext);

    useEffect(() => {
        if (addFocusElement && appRef && (focusOrder !== undefined)) {
            addFocusElement({ focusOrder, elementRef: appRef });
        }
        return;
    }, [addFocusElement, appRef, focusOrder]);

    return (<div ref={appRef}>My custom HTML</div>)
  • setShowcaseApp - you can use this function to send the application to be showcased the the user hovers over it, clicks it, moves focus to it, etc. You can use it likes so:
<div
  onMouseOver={() => setShowcaseApp(app)}
  onMouseLeave={() => setShowcaseApp(undefined)}
  ...

This will display the application in the special showcase component inside of <LaunchPad /> when the user hovers over your custom list item renderer and will clear the application from the showcase component when the user's mouse leaves the div element.

  • markRecentlyUsed - you can use this function to mark the current application being rendered as favorite. Here is an example of marking the application as recently used when the user click's on the application:
<div
  onClick={() => markRecentlyUsed(app)}

The next three methods work with the LaunchPad's context menu. You pass an application to it and the coordinates at which you want the context menu to appear at.

  • setIsContextMenuOpen - tell <LaunchPad /> to open the context menu.

  • setContextMenuCoordinates - the coordinates at which to render the context menu (usually the current mouse x and y coordinates).

  • setAppForContextMenu - the application which the context menu analyses and display different options based on the state of the application (hence the name "context" menu).

Example usage of all of the above mentioned methods:

<div
  onContextMenu={e => {
    setAppForContextMenu(app);
    setContextMenuCoordinates({ x: e.pageX, y: e.pageY });
    setIsContextMenuOpen(true);
  }}

This example will open the context menu with the current application selected at the user's current mouse coordinates, when the user clicks on the list item with the right mouse button.

Adding a component at the top of LaunchPad

This custom component can be added to the top of <LaunchPad /> to display whatever you like. You will not receive any props. Note you must be aware ot the css styling of in order not to break the UI.

<LaunchPad
  components={{
    renderHeaderContents={() => <p>This will show at the very top of LaunchPad</p>}
  }}
/>

Global Search


Adding a custom renderer for a list item

The only thing you can currently customize in <GlobalSearch /> is the list item in the search results:

<GlobalSearch
  components={{
    renderGlobalSearchItem{props => <p>My custom Global Search list item</p>}
  }}
/>

You will receive the following props from <GlobalSearch />:

  • app - this is the internal representation of Glue42 Applications and Glue42 Layouts (global and workspace) that LaunchPad uses. It is the current app of the current row that is being rendered.
  • focusOrder - this is a number that represents the position at which the current list item should receive focus. It is used internally by focus manager of <GlobalSearch />. In order for your renderer to participate in focus switching, you must register it with the FocusArea React context. Otherwise, your renderer will work, but it will not receive focus. Example given below:
    const appRef = useRef<HTMLElement | null>(null);

    const { addFocusElement } = useContext(FocusAreaContext);

    useEffect(() => {
        if (addFocusElement && appRef && (focusOrder !== undefined)) {
            addFocusElement({ focusOrder, elementRef: appRef });
        }
        return;
    }, [addFocusElement, appRef, focusOrder]);

    return (<div ref={appRef}>My custom HTML</div>)
  • setShowcaseApp - you can use this function to send the application to be showcased the the user hovers over it, clicks it, moves focus to it, etc. You can use it likes so:
<div
  onMouseOver={() => setShowcaseApp(app)}
  onMouseLeave={() => setShowcaseApp(undefined)}
  ...

This will display the application in the special showcase component inside of <GlobalSearch /> when the user hovers over your custom list item renderer and will clear the application from the showcase component when the user's mouse leaves the div element.

  • syncRecentWithLP - you can use this function to mark the application as recent in <LaunchPad />. Currently, <GlobalSearch /> does not formally keep track of the recently used applications, so you only need to sync them with the other application:
<div
  onClick={() => syncRecentWithLP(app)}
  • markFavorite - this function can be used to mark the application as favorite. This will cause <GlobalSearch /> to display the application in the Favorites grid to the right of the list Example:
<div
  onClick={() => markFavorite(app)}
  • unmarkFavorite - this function can be used to remove the application from favorites, which will cause <GlobalSearch /> to remove the application from the favorites grid to the right of the list items. This example will unmark the application as favorite whenever the user right clicks on it:
<div
  onContextMenu={() => unmarkFavorite(app)}
  • syncFavWithLP - this function is used to synchronize the favorite applications with <LaunchPad />. Because <LaunchPad /> and <GlobalSearch /> are used as separate applications, internally they use the Glue42 Interop API to understand which applications have been marked as recent or favorite. Note: Every application has a 'persistable' form. You get this from when you call the getPersistableForm() method. You must send the persistable form and from each application or the Glue42 Interop API will throw an error!. Example usage:
<div
  onKeyDown={e => {
    if (e.key === "Enter") {
      markFavorite(app);
      // ATTENTION: SEND THE PERSISTABLE FORM
      syncFavWithLP(app.getPersistableForm());
    }
  }}
  • syncUnfavWithLP - use this function to synchronize and application that was unmarked as favorite. Note: Send the persistable form of the application, which you can get using the getPersistableForm() method of the application. Example:
<div
  onKeyDown={e => {
    if (e.key === "Enter") {
      unmarkFavorite(app);
      // ATTENTION: SEND THE PERSISTABLE FORM
      syncUnfavWithLP(app.getPersistableForm());
    }
  }}

The above examples will mark/unmark the application as favorite in <GlobalSearch /> and synchronize the change with <LaunchPad />.

Change the placeholder

The placeholder can be changed using the placeholder prop.

<GlobalSearch
  placeholder="Search..."
/>

Dependencies (5)

Dev Dependencies (47)

Package Sidebar

Install

npm i @glue42/launchpad-ui-react

Homepage

glue42.com/

Weekly Downloads

19

Version

0.5.8

License

MIT

Unpacked Size

1.69 MB

Total Files

91

Last publish

Collaborators

  • smateev
  • kiril.popov
  • gdavidkov
  • suzunov
  • staafl
  • lkonstantinov
  • flashd2n
  • ppetkow