/lowtide-ui

UI for EAPMM Demo Data Tool

Primary LanguageJavaScript

Lowtide UI

User Interface for Analytics Demo Data Tool by Salesforce's Einstein Analytics Product Marketing Management Team. React client that consumes Lowtide Backend.

DDT Deploy Screen

Installing

You will need to have npm installed on your machine. Clone this repository and move to the root directory. Run npm install to install dependencies. Then you can start development server with npm start, which runs by default on port 3000. Generate a production-optimized build, with npm run build.

Documentation

This project uses React functional components, hooks and Context API. Additionally, it uses React Router for client-side routing, UI components from Material-UI, custom hooks to separate UI from logic, and Sass for custom styling. Deploy and timeshift pages follow the same UI paradigm, with cards on the left representing the tool available resources, and the ones on the right, those that the logged-in user has in their org.

Routing

The application has 3 main routes: /deploy, /timeshift (with their correspondent functionality), and /jobs (which displays the logs the backend sends when the previously mentioned tasks run). Additionally, theres a /login route which display a form for the user to login with their Salesforce account.

The / (home) route, redirects either to the deploy route –if a user is logged in– or to the login route if not. The login route redirects to deploy if a user is already logged in. The three main routes redirect to login if there is no logged-in user.

Context

The application uses React Context API to share state between components. SessionContext.js will be in charge of providing all information about the session (e.g. logged in user, jobs, org info) to all the application. FilterContext.js will be used in the deploy page to communicate the components that set the selected tags and search words (Filterbox.js and SearchBar.js, respectively) with the one that displays the filtered cards (CardContainer.js).

Custom Hooks

Component files should be kept short and focused on UI, so for large and reusable functionality, this project uses Custom Hooks, which is a convention that moves the application logic to their own files and return the data that the component needs to properly render the interface.

useDeployCards.js: Takes type(available/org) as a parameter. Takes care of getting the cards information from the backend API, the tags selected on FilterBox.js and the words inputted on SearchBar.js and returning the list of cards that should be rendered in each CardContainer.

useFilters.js: Takes type(available/org) as a parameter. Handles the functionality of opening and closing the FilterBox component, getting all the tags that can be used, setting the selected tags, removing tags and updating the tags selected in the FiltersContext.

useLogin.js: Is in charge of logging in to the backend application, with information provided in the login screen, and setting up the SessionContext information related to the user.

Components

These are the components used in this project. For ease of comprenhension, this list is ordered in a way that related elements are consecutive.

NavBar

The navbar is rendered in every main route. It displays the tool icon and name, navigation links, the current user and logout button, and the settings button. Takes the following props:

  • activeTab: String. The current page of the application.

SettingsDrawer

Has a config button and the overlayed element that shows the configuration options when the button is clicked. It is a Drawer component from MaterialUI. Takes the following props:

  • position: String. Position where the drawer is going to be shown (top, right, bottom or left)

Card

Each card represents a resource from the Demo Data Tool that can be deployed (or already exists) in the user's org. It is an expandable accordion (From MaterialUI), and displays the template name, author, version , description and tags. Takes the following props:

  • type: String. Type of card to render (available/org).
  • startSelected: Boolean. Works for cards of type available Determines if the card is gonna start with an state of selected (Checkbox checked and blue background).
  • startExpanded: Boolean. Determines if the card is gonna be expanded by default.
  • warning: Boolean. Determines if the card is gonna have a warning badge ("New Template" for repo cards, and "Old template" for org cards). If true for a card of type org it will also make the card background be warning color (see assets/variables.scss).
  • data: Object. Information to be displayed in the card (name, author, version, description, tags).

Checkbox

A custom checkbox that is mainly used by cards of type org, but can be used for different purposes across the app. Uses the Checkbox component from MaterialUI as base. Takes the following props:

  • selected: Boolean. Determines if the checkbox is checked or not by default.
  • setParentSelected: function. A function used to update the parent's selected state from the Checkbox component.

Badge

A custom badge that is mainly used by cards –to indicate that there's a new version (for repo cards) or that it's an old version (for org cards), but can be used for different purposes across the app. Uses the Paper component as its base element. Takes the following props:

  • background: String. Determines the background color of the badge.
  • color: String. Determines the text color of the badge.
  • text: String. Content to be display in the badge.

CardContainer

A component that displays all cards of either type available (repo) or org, and a SearchBar to filter the cards. Rathen than passing the cards as a conventional props, Card Container expects the cards to be passed as childen props in order to render them. It uses Paper component from MaterialUI as base. Takes the following props:

  • title: String. the title to be displayed in the card container.
  • type: String. The type of card container (available/org)
  • styles: Object. Object with the desired width and height of the CardContainer.
  • searchPlaceholder: String. Placeholder for the CardContainer's SearchBar, if not provided the CardContainer will not have a SearchBar.

SearchBar

A bar where the user can enter a keyword or select tags to filter the card results in a CardContainer. It's based on the Paper component from MaterialUI and also uses the InputBase component. Takes the following props:

  • type: String. (available/org). Indicate which type of SearchBar to render, in order to control the functionality of searching for its correspondant CardContainer.
  • placeholder: String. Placeholder of the SearchBar.

FilterBox

Based on the Popover and Button component from MaterialUI, it can be opened to select the filters that the user wants to filter the Card results by. Takes the type (available/org) as a prop. The Popover is showed when the button is clicked, and closed with a button inside it, or by simply clicking in any other area of the screen.

When filters are selected in the FilterBox, it's only reflected in the component own state. The user would have to hit the Save button in order to update the filters in the FiltersContext, and so be reflected in the CardsContainer (deploy page).

Tag

Based on the Chip component from MaterialUI, it represents a tag of the tool templates. It's used both in the cards to show the specific template tags, and in the FilterBox to show all tags available; it can be clickable or deletable (mainly useful fot the FilterBox component). Takes the following props:

  • label: String. The text to be displayed in the Tag.
  • selected: Boolean.Determines fi the chip is selected (To give it an accent background).
  • handleChipClick: function. To be executed in the parent component when the Tag is clicked. If this prop is not provided, then the Tag won't be clickable.
  • handleDelete: function. To be executed in the parent component when the Tag is deleted. If this prop is not provided, then the Tag won't be deletable.

Next Steps

  • Implement real functionality by making calls to Lowtide Backen server.
  • Refactor some code to make escalation easier (e.g. Making a base card component with the custom styles and wrap other cards to give them the same look).