# datahub

datahub is a frontend available as a [Node.js](https://nodejs.org/en/) package. It is based on the [React](https://reactjs.org/) framework. Through a web interface, this application provides:

- a user authentication portal
- a GUI for scientific metadata management
- a GUI for the electronic logbook which can complement data
- experimental data downloading feature
- manual DOI minting feature

Currently, datahub depends on:

- ICAT+ package. ICAT+ is the backend which stores logbook events
- [ICAT](https://icatproject.org) metadata catalogue. ICAT stores metadata and handles the user authentication mechanism

# Menu

1. [Installation](#installation)
2. [Configuration](#configuration)
3. [Developments](#developments)

# Installation

## Prerequisite:

1. Make sure the dependencies mentioned above are installed and properly configured.

## Installation procedure

1. Download the source code from [gitlab](https://gitlab.esrf.fr/icat/E-DataPortal) repository
2. Install dependencies

```bash
npm install
```

3. Configure datahub app. See this [section](#configuration).

4. Run the app

```bash
npm start
```

# Configuration

Datahub configuration is spread among different files located in the folder **src/config**. These files are:

- [icat.js](#icatjs) : configure access to the metadata catalogue.
- [icatPlus.js](#icatplusjs) : configure access to the ICAT+ server
- [techniques.js](#techniquesjs) : configure the known techniques
- [gui.config.js](#guiconfigjs) : configuration file for the logbook (to be moved to config.js)
- [config.js](#configjs) : UI general configuration of the GUI

Example files for [icat.js](src/config/icat/icat.example.js) and [icatPlus.js](src/config/icat/icatPlus.example.js) are provided and needs to be copied in configuration file:

You can copy them manually:

```bash
cp src/config/icat/icat.example.js src/config/icat/icat.js
cp src/config/icat/icatPlus.example.js src/config/icat/icatPlus.js
```

or run:

```
npm run-script configure
```

## icat.js

Edit the file **icat.js** with your favorite text editor and set the configuration to access the metadata catalogue following the indications below.

<!--START configurationICAT -->

```js
/**
 * icat.example.js configuration file
 */
var ICAT = {
  authentication: {
    /** Single sign-on configuration */
    sso: {
      enabled: true,
      /** ICAT authentication plugin for json web tokens */
      plugin: 'esrf',
      /** Configuration to be passed to keycloak.js (https://github.com/keycloak/keycloak-documentation/blob/master/securing_apps/topics/oidc/javascript-adapter.adoc) */
      configuration: {
        realm: 'ESRF',
        url: 'https://websso.esrf.fr/auth/',
        clientId: 'icat',
      },
    },
    /** Anonymous user's credentials*/
    anonymous: {
      enabled: true,
      /** ICAT plugin used for authentication. */
      plugin: 'db',
      /** Username for the anonymous user */
      username: 'reader',
      /** Password for the anonymous user */
      password: 'reader',
    },
    authenticators: [
      {
        plugin: 'esrf',
        /** title will be displayed as the title of the Tab at the login Form */
        title: 'ESRF',
        /** If will be hidden in the login form */
        hidden: false,
      },
      {
        plugin: 'db',
        title: 'Database',
        hidden: false,
      },
    ],
  },
};

export default ICAT;
```

<!--END configurationICAT -->

## icatPlus.js

Edit the file **icatPlus.js** with your favorite text editor and set the configuration to access the ICAT+ application following the indications below.

<!--START configurationICATPlus -->

```js
/**
 * icatPlus.example.js configuration file
 */
var ICATPLUS = {
  /** URL of ICAT+ server */
  server: 'https://icatplus.esrf.fr',
};

export default ICATPLUS;
```

<!--END configurationICATPlus -->

## techniques.js

The file [techniques.js](src/config/techniques/techniques.js) complements short named techniques as stored in ICAT metadata catalogue. It maps a short name to a description and display settings.

To add a new technique, use the following object to fully define the technique.

```js
/** Object defining the new technique */
{
/** Full name of the technique */
name: "Ptychography",
/** Short name of the technique as stored in ICAT */
shortname: "PTYCHO",
/** Full description of the technique */
description: "Ptychography is a technique invented by Walter Hoppe that aims to solve the diffraction-pattern phase problem by interfering adjacent Bragg reflections coherently and thereby determine their relative phase.",
/** Font color */
color: "#97E0FE"
},
```

## gui.config.js

Edit the file [gui.config.js](src/config/gui.config.js) with your favorite text editor and set the GUI configuration following the indications below.

<!--START configurationGUI -->

```js
```

<!--END configurationGUI -->

## ui.config.js

<!--START config -->

```js
var UI = {
  status: {
    offline: {
      enabled: false,
      message: "Sorry, we're down for scheduled maintenance right now.",
    },
  },
  menu: {
    applicationTittle: 'Data Portal',
    isSearchVisible: true,
    isClosedDataVisible: true,
    isOpenDataVisible: true,
    isMySelectionVisible: true,
  },
  loginForm: {
    header: '',
    /** Text displayed on top of the username sigin form. Someone can customize the text as: User office account, ESRF Account, Umbrella account, etc... */
    usernameLabel: 'Username',
    sso: {
      title: 'Sign in with SSO',
      buttonText: 'ESRF SSO',
    },
  },
  investigationContainer: {
    isDatasetListVisible: true,
  },
  logbook: {
    /** Number of logbook events to display per page. EVENTS_PER_PAGE should be lower than EVENTS_PER_DOWNLOAD */
    EVENTS_PER_PAGE: 100,
    /** Maximum number of logbook events downloaded from the server. This enables to store a larger set of
        events than those required for a single page thus reducing HTTP requests to the server. */
    EVENTS_PER_DOWNLOAD: 300,
    /* the field used to sort events. Most of the time 'creationDate' is used. Possible values: 'creationDate', '_id', 'createdAt', 'updatedAt' */
    SORT_EVENTS_BY: '_id',
    /* the order the events sorted by SORT_EVENTS_BY will be ordered. Possible values: 1 (for ascending order), -1 (for descending order)*/
    SORTING_ORDER: -1,
    /** Tinymce editor minimum height when there is a single editor in the modal */
    SINGLE_EDITOR_MIN_HEIGHT: '200px',
    /** Tinymce editor maximum height when there is a single editor in the modal */
    SINGLE_EDITOR_MAX_HEIGHT: '808px',
    /** Tinymce editor minimum height when there are 2 editors in the modal */
    DUAL_EDITOR_MIN_HEIGHT: '270px',
    /** Tinymce editor maximum height when there are 2 editors in the modal */
    DUAL_EDITOR_MAX_HEIGHT: '270px',
    /* Default tag color used in the logbook when tag color is not set */
    DEFAULT_TAG_COLOR: '#a6bded',
    /* Refresh event list periodically with a time interval defined by AUTOREFRESH_DELAY when new events arrived.
     * When it is set to false, the event list is not refreshed but the amount of new events which arriived is shown.*/
    AUTOREFRESH_EVENTLIST: true,
    /* Time interval between requests checking whether new events arrived. (in milliseconds) */
    AUTOREFRESH_DELAY: 20000,
  },
  footer: {
    text: 'European Synchrotron Radiation Facility',
  },
};

export default UI;
```

<!--END config -->

# Developments

- [Tests](#tests)
- [Code quality](#code-quality)
  - [Automatic fixing and formatting](#automatic-fixing-and-formatting)
  - [Editor integration](#editor-integration)
- [Widgets](#Widgets)
  - [ResponsiveTable](#responsivetable)
  - [Loader](#loader)

## Tests

Run:

```
npm test
```

## Code quality 🔎

- `npm run lint` - run linting and code formatting commands
- `npm run lint:eslint` - lint all JS files with ESLint (this command will report warnings as errors)
- `npm run lint:prettier` - check that all files have been formatted with Prettier

### Automatic fixing and formatting

- `npm run lint:eslint -- --fix` - auto-fix linting issues
- `npm run lint:prettier -- --write` - format all files with Prettier

### Editor integration

Most editors support fixing and formatting files automatically on save. The configuration for VSCode is provided out of
the box, so all you need to do is install the recommended extensions.

## Widgets

### ResponsiveTable

This widget is based on react-bootstrap-table2 (https://react-bootstrap-table.github.io/react-bootstrap-table2/) but adds responsiveness.

Columns can now be configured based on the size of the device as bootstrap does (xs, sm, md, lg)

Configuration:

```js
const columns = [
  {
    text: 'Proposal',
    dataField: 'name',
    headerStyle: (column, colIndex) => {
      return { width: '50%', textAlign: 'center' };
    },
    responsiveHeaderStyle: {
      xs: { width: '20%', textAlign: 'center' },
      sm: { width: '50%', textAlign: 'center' },
      md: { width: '70%', textAlign: 'center' },
      lg: { width: '90%', hidden: true, textAlign: 'center' },
    },
  },
];

var pageOptions = {
  showTotal: true,
  hidePageListOnlyOnePage: true,
  sizePerPageList: [
    {
      text: '5',
      value: 5,
    },
    {
      text: '10',
      value: 10,
    },
    {
      text: 'All',
      value: data.length,
    },
  ],
};

<ResponsiveTable data={data} columns={columns} pageOptions={pageOptions} />;
```

If there is no responsiveHeaderStyle then headerStyle will be used as default. If there is no the used screen size (xs, sm, md, lg) configured in the responsiveHeaderStyle attribute then headerStyle will be used by default.

You may specify which field of the table is unique by passing a `keyField` prop. If you omit it, the default is `"id"`.

### Loader

It informs users that data are still been loaded

```js
// With default loading message
<Loader />
```

```js
// With custom loading message and space above/below
<Loader message="Loading authors..." spacedOut />
```

```js
// When used inside a Bootstrap `Panel`
<Loader message="Loading datasets..." inPanel />
```
