@glue42/launchpad-ui-react
v0.5.8
Published
Glue42 Launchpad and GlobalSearch React Components
Downloads
188
Readme
Glue42 Launchpad and Global Search ·
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
andGlue42 Layouts (global and workspace)
thatLaunchPad
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 theFocusArea
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 theGlue42 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
andGlue42 Layouts (global and workspace)
thatLaunchPad
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 theFocusArea
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
andGlue42 Layouts (global and workspace)
thatLaunchPad
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 theFocusArea
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
andGlue42 Layouts (global and workspace)
thatLaunchPad
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 theFocusArea
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 theGlue42 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..."
/>