Skip to content

SE Onboarding Document

GERLITO CHAGAS edited this page Jun 13, 2023 · 8 revisions

Introduction

This document provides an overview of how the website was built and documents the decisions done with regards to the implementation.

Table of Contents

  1. Setting up
  2. Tech Stack
  3. User Flow
  4. Types
  5. Pages
  6. Contexts
  7. Filtering & Searching

Setting up

Here are some links to get you started:

Please refer to the Github issues to view the acceptance criteria for each feature. For Figma mockups, please reach out to Sam.

Tech Stack

As detailed in the README, the tech stack used in this website includes:

  • Vite with React & TypeScript
  • Tailwind CSS v3
  • Ant Design (for complex components)
  • Dayjs (date utility library)
  • Ant Design Icons

Every PR merged to main gets deployed to Github Pages. Also note that Ant Design and Tailwind styles sometimes clash. Check if this can be resolved by updating the theme. If not, feel free to add custom CSS in index.css.

Flow

The user journey starts when a data provider wants to add a dataset/model to the research bank. They fork and submit a PR of their entry based on the sample-catalog-item.yml which goes under a validation process through Github Actions. Once the PR has successfully passed the tests and merged, the entry will be deployed to the website.

In the website, the catalogue items are fetched from the catalog.json (which contains all the yaml files merged in one) on the initial load. This is being done because the list of catalogue items as of now is very small. The filter options for country, organization, and tags are also generated on the first load from the catalog.json. These filter options are structured in a way that it gets the unique values for each field (country, organization, tags) and lists down the catalogue IDs that have these values. See the getCountryOptions, getOrganizationOptions, and getTagsOptions methods in Filter.util.ts.

When users want to explore the website, they can search or filter through the results and view the resulting metadata of their selected entry.

General Styling

Antd Components

Most of the complex components in this project are built around antd components like this button component. All antd components subscribe to a preset color theme out of the box but this can be modified by passing a theme object as an attribute to the ConfigProvider.

More info in what tokens can be used to further customize the theme can be found here

// App.tsx

const theme = {
  //modify theme of all components
  token: {
    colorPrimary: '#24295c',
	colorPrimaryBg: '#ddcccb',
	colorLinkHover: '#24295c',
	lineHeightLG: 1.39
	},
  // modify theme of a single component
  components: {
	Pagination: {
  	  borderRadius: 0
    }
  }
}

export default function App(): ReactElement {
  return(
    <ConfigProvider theme={theme}>
  )
}


Image Sources

Image sources can come from one of two sources

  • /public/assets

Images here are typically generated based

  • /src/assets

Images in this folder are not dynamically generated. Some example images here include the unicef logo or the hero banner logo in the landing page, both of which are not generated from any of the catalog yaml files.

import CatalogueHeroImg from '../assets/catalogue-hero-bg.jpg'

<img src={CatalogueHeroImg}/>

Types

The discussion for the types started in this thread. Feel free to discuss items related to the types and schema here.

In the frontend, there are two types:

  • CatalogueItem.type.ts - type for each catalogue item
  • SearchFilters.type.ts - types for filters and search

The DateFilterType in SearchFilters.type.ts is used as the type for Ant Design's RangePicker component. This type uses the RangeValue type from another library (rc-picker) which is the underlying component used in Ant Design. See the StackOverflow thread here.

Pages

There are three main pages on the website:

  • Landing page
  • Catalogue page (/catalogue)
  • Catalogue item page (/catalogue/<catalogue-item-id>)
  • Contribution page (/contribute)

Contexts

Because the catalogue items and filter options are generated on initial load, these are being passed to the different pages through contexts. Currently, there are three contexts in the frontend:

  • CatalogueItemContext
  • FilterContext
  • SearchContext

The CatalogueItemContext contains the method to fetch the original list of catalogue items. It also holds the filteredCatalogueItems which is being set during filtering, and the featuredItems. The catalogue items are based on catalog.json while the featured items are based on featured.json. Both are under the public/api/data directory. The methods for fetching the data are in api/index.ts.

The FilterContext contains all states and methods related to filtering. Generating the filter options on first load is also done in the provider. Note that the searchValue is included in the filters object since it's used together with the other filters to update search results.

The SearchContext contains all states and methods related to generating search options. The search bar is an autocomplete that returns search suggestions on input change. This context handles this specific feature. Not to be confused with search results, the search options are based on the original list of catalogue items and are not related nor affected by the filters.

Filtering and Searching

The search results on the catalogue page get updated every time a filter is changed or a user has initiated a search (clicking on the search button or pressing enter). The filtering makes use of the catalogueIds attributed to the value of the filter.

The flow for filtering catalogue items is:

  1. Get union of catalogue item IDs for each filter - because the filters are multi-select, a union is performed to get all possible catalogue item IDs that match either of the values of one filter. The search and year filters follow the same logic except that it compares against the original catalogue items to get the list of catalogue item IDs.
  2. Get intersection of catalogue item IDs against filters that are not empty - to consolidate all filters, the common catalogue item IDs that exist on all filters are taken. Empty filters are excluded because it is assumed that all options are accounted for.
  3. Filter the original catalogue items with the final list of catalogue item IDs

These steps are detailed inside the filterCatalogueItems method in FilterContext.tsx. See utils/Filters.util.ts for the more granular methods on filtering.

For more info on how this was conceptualized, see this thread.

Adding Tests