Home overview

The Home component of OpenFin Workspace provides a text box interface for your users to enter supported commands or search for content you provide as part of your implementation.

How it works

To make content or applications available, you register a Home provider. If multiple providers are registered with OpenFin Home, their entries are shown in the Home toolbar.

The HomeProvider interface extends the CLIProvider interface. In the current version of Workspace, these interfaces are identical, and some examples call CLIProvider, while others call HomeProvider. A best practice is to work with HomeProvider to make sure your Workspace implementation is compatible with future versions.

A HomeProvider can do the following:

  • Integrate with OpenFin Home.
  • Return customizable search results to Home, which can include suggested searches and filtering options.
  • Starting in Workspace 8, configure search results to be returned asynchronously, to improve performance. For more information, see Support asynchronous search results.
  • Set a logo icon to be displayed when the provider is selected.
  • Starting in Workspace 10, support complex search query strings programmatically with a new API. See Support complex search queries programmatically for details.

Starting in Workspace 9, the Home UI is hidden by default on startup. To show Home by default instead, call the Home.show() method when you register your provider. See Create your provider in this article.

Get started

The basic steps:

  1. Implement the HomeProvider interface (or CLIProvider).

  2. Register your provider with the HomeApi.

Prerequisites

Node and npm.

Install and import

  1. Install the Workspace npm package:

    npm i -E @openfin/workspace
    
  2. Import OpenFin Workspace:

    import {
         Home,
         CLIProvider,
         CLISearchListenerRequest,
         CLISearchResult,
         CLISearchListenerResponse,
         CLISearchResponse,
         CLIDispatchedSearchResult,
         App
     } from "@openfin/workspace";
    

Create your provider

  1. Define and register your CLIProvider object:

    const cliProvider: CLIProvider = {
        title: "My title",
        name: "My provider name",
        icon: "url to icon",
        onUserInput: onUserInput,
        onResultDispatch: onResultDispatch,
    };
    
    await Home.register(cliProvider);
    // override default, which is to hide on startup    
    await Home.show();
    

    The onUserInput property points to a function that is called when the user enters a search term. The onResultDispatch points to a function that is called when the user selects a search result.

  2. Create the onUserInput function. This could be as simple as the following example, or it can be a query builder app, for example, that takes advantage of the new setQueryString function in Workspace 10.

    const onUserInput = async (
        request: CLISearchListenerRequest,
        response: CLISearchListenerResponse
        ): Promise<CLISearchResponse> => {
            const query = request.query.toLowerCase();
            if (query.indexOf("/") === 0) {
                return { results: [] };
            }
            
            // integrators list of Apps
            const apps: App[] = await getApps();
            
            const results: CLISearchResult<any>[] = apps
                .map((app) => {
                    return {
                        key: app.appId,
                        title: app.title,
                        actions: [{ name: "launch-app", hotkey: "enter" }],
                        data: app,
                        template: "Plain",
                    };
                })
                .filter((entry) => {
                    return entry.title.includes(query);
                });
            
            const result: CLISearchResponse = {
                results,
            };
            
            return result;
    };
    
  3. Create the onResultDispatch function:

    const onResultDispatch = async (result: CLIDispatchedSearchResult) => {
     if (result.data !== undefined) {
         await launchApp(result.data);
     } else {
         console.warn("Unable to execute result without data being passed");
     }
    };
    

The full source code

Here is a complete file for creating and registering a CLI Provider. See the Workspace Starter example for the full context for this file.

import { Home, CLIProvider, CLISearchListenerRequest, CLIFilter, CLISearchResult, CLISearchListenerResponse, CLISearchResponse, CLIDispatchedSearchResult, launchApp  } from "@openfin/workspace";
import { getApps } from "./apps";

const providerName = "register-with-home-basic";

async function getResults(query?: string) : Promise<CLISearchResponse> {
   
    let apps = await getApps();

    if(Array.isArray(apps)){
        
        let initialResults: CLISearchResult<any>[] = [];

        for(let i = 0; i < apps.length; i++) {
            if(apps[i].description !== undefined) {
                let entry: any = {
                    key: apps[i].appId,
                    title: apps[i].title,
                    actions: [{ name: "launch-app", hotkey: 'enter' }],
                    data: apps[i],
                    description: apps[i].description,
                    shortDescription: apps[i].description,
                    template: "SimpleText",
                    templateContent: apps[i].description,
                };
                initialResults.push(entry);
            } else {
                let entry: any = {
                    key: apps[i].appId,
                    title: apps[i].title,
                    actions: [{ name: "launch-app", hotkey: 'enter' }],
                    data: apps[i],
                    template: "Plain"
                };
                initialResults.push(entry);
            }
        }

        let finalResults;

        if(query === undefined || query === null || query.length === 0) {
            finalResults = initialResults;
        } else {
            finalResults = initialResults.filter(entry => {
              let targetValue = entry.title;
                        
              if(targetValue !== undefined && targetValue !== null && typeof targetValue === "string") {
                  return targetValue.toLowerCase().indexOf(query) > -1;
              }
              return false;
            });
        }

        let response: CLISearchResponse = {
            results: finalResults
        };

        return response;
    } else {
        return {
            results:[]
        };
    }
}

export async function register(): Promise<void> {
    console.log("Initialising home.");

    const queryMinLength = 3;

    const onUserInput = async (request: CLISearchListenerRequest, response: CLISearchListenerResponse): Promise<CLISearchResponse> => {
        let query = request.query.toLowerCase();
        if(query.indexOf("/") === 0) {
            return {results: [] };
        }

        if(query.length < queryMinLength) {
            return getResults();
        }

        return getResults(query);
    };

    const onSelection = async (result:CLIDispatchedSearchResult) => {
        if (result.data !== undefined) {
            await launchApp(result.data);
        }  else {
            console.warn("Unable to execute result without data being passed");
        }
    };

    const cliProvider:CLIProvider = {
        title: "Basic Workspace Platform",
        name: providerName,
        icon: "http://localhost:8080/favicon.ico",
        onUserInput: onUserInput,
        onResultDispatch: onSelection,
     };

     console.log("Home configured.");

    return Home.register(cliProvider);
}

export async function deregister() {
  return Home.deregister(providerName);
}

export async function show() {
    return Home.show();
}

export async function hide() {
    return Home.hide();
}