Source: @@actions/load.js

/**
 * @file Handles loading of the model
 * @module @@actions/load.js
 */

import { onDataLoaded } from '@@actions/lifecycle';
import { Graph } from '@@graph';
import { fetchDataSchema } from '@@api';
import { dispatch, dispatchSet, getState } from '@@app-state';
import { invertObj, view } from 'ramda';
import * as ModelState from '@@app-state/model/state';
import { fetchFile, hasPermissions } from '@@actions/solid/files';
import { withLoadingP, withLoading } from '@@components/with-loading';
import { loadHumanReadableData } from '@@actions/load-human-readable';
import { message, Modal } from 'antd';
import {notification} from 'antd';
import LoadingLabelsFeedback from '@@components/controls/loading-labels-feedback';
import { applyCustomPrefixes, loadCustomPrefixes } from '@@actions/custom-prefix';
import { translated } from '@@localization';
import * as ControlState from '@@app-state/controls/state';
import { getLastLocalState } from '@@storage';
import * as SettingsState from '@@app-state/settings/state';
import * as ControlsState from '@@app-state/controls/state';

/**
 * Loads the graph for the provided URL.
 * Downloads it and initializes it while displaying notification in the process.
 * @function
 * @param url
 * @returns {Promise<void>}
 */
const loadGraph = async url => {
  const {prefixes, schemaData} = await withLoadingP(translated('Fetching RDF Schema...'))(fetchDataSchema(url));
  dispatchSet(ModelState.prefixes, invertObj(prefixes));
  Graph.clear();
  withLoading(translated('Initializing graph...'))(Graph.initialize(schemaData));
};

/**
 * Loads human readable labels.
 * @function
 */
export const loadLabels = () => {
  const key = 'loading-labels-notification';
  notification.info({key, message: translated('Loading labels'), duration: 0, description: LoadingLabelsFeedback()});
  loadHumanReadableData().finally(() => notification.close(key));
};

/**
 * Loads the application model from a remote URL.
 * @function
 * @param modelURL URL of the model file to load.
 * @returns {Promise<boolean|*|undefined>}
 */
const loadDataFromFile = async modelURL => {
  try {
    const json = await withLoadingP(translated('Fetching file...'))(fetchFile(modelURL).then(data => data.json()));

    loadModel(json);
    loadLabels();
    Modal.destroyAll();

    return await hasPermissions(modelURL, true);
  } catch (e) {
    console.error(e);
  }
};

/**
 * Loads new graph from provided URL.
 * @function
 * @param dataSchemaURL
 * @returns {Promise<void>}
 */
const loadNewGraph = async dataSchemaURL => {
  try {
    await loadGraph(dataSchemaURL);
    onDataLoaded();
    loadLabels();
  } catch (e) {
    console.error(e);
    message.error(translated('An error occurred while trying to download the schema.'));
  }
}

/**
 * Polymorphic function.
 * Loads the graph based on whether it receives data schema URL or a model file URL.
 * @param modelURL
 * @param dataSchemaURL
 * @param endpointURL
 * @returns {Promise<{hasPermissions: boolean, modelURL}>}
 */
export const loadGraphFromURL = async ({modelURL, dataSchemaURL, endpointURL}) => {
  dispatchSet(ControlState.loaded, false);
  let hasPermissions = false;
  if (modelURL) {
    hasPermissions = await loadDataFromFile(modelURL);
  } else {
    await loadNewGraph(dataSchemaURL);
    dispatchSet(ModelState.dataSchemaURL, dataSchemaURL);
    if (endpointURL) {
      dispatchSet(ModelState.endpoint, endpointURL);
    }
  }
  dispatchSet(ControlState.loaded, true);
  dispatch(applyCustomPrefixes(view(ModelState.customPrefixes, getState())));
  dispatchSet(ModelState.dirty, false);

  return {modelURL, hasPermissions};
};


/**
 * @function
 */
export const loadLocalSettings = () => {
  const settings = getLastLocalState().settings;
  if (settings) {
    dispatchSet(SettingsState.rootLens, Object.assign(SettingsState.initial, settings));
  }
}

/**
 * Loads the model from json and initializes the graph.
 * @function
 * @param json
 */
export const loadModel = json => {
  dispatchSet(ControlsState.importingModelFile, true);
  const newData = view(ModelState.rootLens, json);
  Graph.clear();
  withLoading('Initializing graph...')(Graph.initialize(json));
  dispatchSet(ModelState.rootLens, newData);
  dispatch(loadCustomPrefixes(view(ModelState.customPrefixes, getState())));
  Graph.updatePositions(view(ModelState.classes, getState()));
  dispatchSet(ControlsState.importingModelFile, false);
}

/**
 * Loads model data from browser storage.
 * @returns {Promise<void>}
 */
export const loadLocalData = async () => {
  const state = getLastLocalState();
  loadModel(state);
  const dataSchemaURL = view(ModelState.dataSchemaURL, getState());
  withLoadingP('Fetching RDF Schema...')(fetchDataSchema(dataSchemaURL))
    .then(({prefixes}) => dispatchSet(ModelState.prefixes, invertObj(prefixes)))
    .catch(() => message.error(translated('There was a problem downloading prefixes for this file.')))
    .finally(() => {
      loadLabels();
      dispatchSet(ModelState.dirty, false);
    });
};