SmartExtractSimple API Examples

Data Extraction Example

import { SmartExtactSimple } from '@clik-ai/smart-extract';

const smex = new SmartExtractSimple();

// Instead of assigning to a global variable you'll need to persist
// the extracted data in a DB
let extractedData = null;

// SmartExtract needs the input file to be encoded as a Data URL.
// You may have your users select a file in browser and encode it as a Data URL
// or you may get the file as Data URL from an API
// See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs

async function extractData(token) {
  const { fileDataUrl, fileName } = await getFileData();

  return smex.extractDocumentData({
    session: {
      mountNode: document.getElementById('smex-wrapper-div'),
      sessionAuthToken: token,
      // for multi-extraction
      // multiple: true,
    },
    file: fileDataUrl,
    fileName,
  });
});

// Get auth token and start SmartExtract session
getAuthToken().then(async (token) => {
  extractedData = await extractData(token);
  if (extractedData !== null) {
    console.log('Extracted data: ', extractedData);
  } else {
    console.log('User cancelled data extraction');
  }
});

Edit Extracted Data Example

import { SmartExtactSimple } from '@clik-ai/smart-extract';

const smex = new SmartExtractSimple();

// Instead of assigning to a global variable you'll need to update
// the extracted data in the DB
let updatedExtractedData = null;

async function editData(token) {
  const previouslyExtractedData = await getPreviouslyExtractedData();

  return smex.extractDocumentData({
    session: {
      mountNode: document.getElementById('smex-wrapper-div'),
      sessionAuthToken: token,
    },
    data: previouslyExtractedData
  });
});


// Get auth token and start SmartExtract session
getAuthToken().then(async (token) => {
  updatedExtractedData = await editData(token);
    if (updatedExtractedData !== null) {
    console.log('Extracted data: ', extractedData);
  } else {
    console.log('User cancelled data extraction');
  }
});

Disable Retry Flow and Handle Error

SmartExtract by default triggers a retry flow in case data extraction for a document fails. In case user provided some meta information incorrectly, this gives them a chance to re-fill the form and try extraction again. However, if you want to handle error within client application you may disable the retry flow. When the retry flow is disabled, the returned promise will be rejected in case of an error in data extraction

async function extractData(token) {
  const { fileDataUrl, fileName } = await getFileData();

  return smex.extractDocumentData({
    session: {
      mountNode: document.getElementById('smex-wrapper-div'),
      sessionAuthToken: token,
    },
    file: fileDataUrl,
    fileName,
    options: {
      disableRetry: true,
    }
  });
});

// Get auth token and start SmartExtract session
getAuthToken().then(async (token) => {
  try {
    extractedData = await extractData(token);
  } catch() {
    console.error('SmartExtract failed to extract document data');
  }
});

Styling and Customisations

SmartExtract provides various options so that you can style different elements on the SmartExtract component to match the look and feel of your application. Following are complete type definition for all the customisation options that you can provide:

// Options to be passed to the extractDocumentData API
export interface ExtractOptions {
  // cutomisation options for extraction form
  form?: FormConfig,
  // cutomisation options for the spreadsheet view
  spreadsheet?: SpreadsheetConfig,
  // cutomisation options for the retry section
  retrySection?: RetrySectionConfig,
  // option to disable retry flow
  disableRetry?: boolean,
}

// Options to configue a text element
export interface TextConfig {
  // the text to display
  text?: string,
  // inline styles to apply to the text element
  style?: CSS.Properties,
}

// Options to configue a button element
export interface ButtonConfig {
  // label to display on the button
  label?: string,
  // inline style to apply to the button
  style?: CSS.Properties,
  // change default visibility of the button
  visible?: boolean,
}

// Options to customise extraction form
export interface FormConfig {
  // Title displayed above the form
  title?: TextConfig,
  // Configuration options for multi-extract form specific elements
  multiExtract?: MultiExtractOptions,
  // meta data field options
  fields?: {
    // Asset type field options 
    assetType?: AssetTypeFieldConfig,
    // Document type field options
    documentType?: DocumentTypeFieldConfig,
    // Page range field options
    pageRange?: PageRangeFieldConfig,
    // Sheet name field options
    sheetName?: SheetNameFieldConfig,
    // OS period field options
    osPeriod?: OSPeriodFieldConfig,
    // Submit button options (always visible)
    submit?: Omit<ButtonConfig, 'visible'>,
    // Cancel button options
    cancel?: ButtonConfig,
  }
}

// Configuration options for multi-extract form specific elements
export interface MultiExtractOptions {
  // options for various buttons
  buttons?: {
    // Add tagging button (always visible)
    addTagging?: Omit<ButtonConfig, 'visible'>,
    // Button to expand/collapse tagging options (always visible)
    selectTagging?: Omit<ButtonConfig, 'visible'>,
    // Button to delete a tagging (always visible, icon button)
    deleteTagging?: Omit<ButtonConfig, 'visible' | 'label'> & DeleteTaggingExtraOptions
  },
}

// Extra options for the delete tagging button
export interface DeleteTaggingExtraOptions {
  // Tooltip displayed on the button
  tooltip?: {
    // Tooltip when the button is enabled
    text?: string,
    // Tooltip when the button is disabled i.e. if it's the only tagging
    disabled?: string,
  },
  // Options for the confirm popup that shows
  confirm?: {
    // Title shown on the popup
    title?: TextConfig,
    // Message displayed on the popup
    message?: TextConfig,
    // Buttons on the popup
    buttons?: {
      // Confirm delete button (always visible)
      ok?: Omit<ButtonConfig, 'visible'>,
      // Cancel delete button (always visible)
      cancel?: Omit<ButtonConfig, 'visible'>,
    }
  }
}

// Valid asset types
export type AssetType =
  'MULTIFAMILY' |
  'STORAGE' |
  'CONDO' |
  'SENIOR_HOUSING' |
  'MOBILE_HOME_PARK' |
  'HEALTHCARE' |
  'HOTEL' |
  'OFFICE' |
  'RETAIL' |
  'INDUSTRIAL' |
  'PARKING_GARAGE'

// Asset type field options
export interface AssetTypeFieldConfig {
  // Field label
  label?: string,
  // Options to show in the dropdown
  options?: { label: string, value: AssetType }[],
  // Style options for the field elements
  style?: {
    // styles for the dropdown
    select?: CSS.Properties,
    // styles for dropdown options 
    option?: CSS.Properties,
    // style for field label
    label?: CSS.Properties,
  },
}

// Valid document types
export type DocumentType =
  'OPERATING_STATEMENT' |
  'OPERATING_STATEMENT_BUDGET' |
  'OPERATING_STATEMENT_PROFORMA' |
  'RENT_ROLL'

// Document type field config
export interface DocumentTypeFieldConfig {
  // Field label
  label?: string,
  // Options to show in the dropdown
  options?: { label: string, value: DocumentType }[]
  // Style options for the field elements
  style?: {
    // styles for the dropdown
    select?: CSS.Properties,
    // styles for dropdown options     
    option?: CSS.Properties,
    // style for field label    
    label?: CSS.Properties,
  },
}

// Page range field options
export interface PageRangeFieldConfig {
  // Field label
  label?: string,
  // Styles for various field elements
  style?: {
    // style for field label    
    label?: CSS.Properties,
    // styles for the start page input field
    startInput?: CSS.Properties,
    // styles for the end page input field
    endInput?: CSS.Properties,
    // styles for the clear field button
    clearButton?: CSS.Properties,
  },
}

// Sheet name selection field
export interface SheetNameFieldConfig {
  // Field label
  label?: string,
  // Styles for various field elements
  style?: {
    // styles for the dropdown  
    select?: CSS.Properties,
    // styles for dropdown options       
    option?: CSS.Properties,
    // style for field label    
    label?: CSS.Properties,
  },
}

// Operating statement period field
export interface OSPeriodFieldConfig {
  // Field label
  label?: string,
  // Styles for various field elements  
  style?: {
    // Style for start month picker
    startInput?: CSS.Properties,
    // Styles for end month picker
    endInput?: CSS.Properties,
    // Styles for field label
    label?: CSS.Properties,
    // Styles for the clear field button
    clearButton?: CSS.Properties,
    // Styles for the period dropdown
    select?: CSS.Properties,
    // Styles for the period dropdown options
    option?: CSS.Properties,
  },
}

// Options to configure the spreadsheet view
export interface SpreadsheetConfig {
  // Options to configure the buttons on spreadsheet view
  buttons?: {
    // Save button options
    save?: ButtonConfig,
    // Cancel button options
    cancel?: ButtonConfig,
    // Download button options (hidden by default)
    download?: ButtonConfig,
  },
}

// Retry section options
export interface RetrySectionConfig {
  // Error message displayed
  message?: TextConfig,
  // Button options
  buttons?: {
    // Retry button options
    retry?: ButtonConfig,
    // Cancel button options
    cancel?: ButtonConfig,
  },
}
// An options object conforming with the above mentioned 
// specification can be passed to the extractDocumentData API

const smartExtractConfigOptions: ExtractOptions = {...}

smex.extractDocumentData({
  session: {
    mountNode: document.getElementById('smex-wrapper-div'),
    sessionAuthToken: token,
  },
  file: fileDataUrl,
  fileName,
  
  options: smartExtractConfigOptions
});

ReactJS Integration

If you want to use SmartExtract with in your ReactJS application, you can wrap the SmartExtract API in a simple hook that you can use in your components:

export function useSmartExtractSimple() {
  const smex = React.useMemo(() => new SmartExtractSimple(), []);

  const endSession = React.useCallback(() => smex.endSession(), [smex]);

  const extractDocument = React.useCallback(async ({ data, token, iframeWrapper, multiple }) => {
    // cleanup any previously open session
    smex.endSession();
    const { fileDataUrl, fileName, ...rest } = data;

    return smex.extractDocumentData({
      session: {
        multiple,
        sessionAuthToken: token,
        mountNode: iframeWrapper,
        closeOnComplete: true,
      },
    
      file: fileDataUrl,
      fileName,
    
      data: rest,
    });
  }, [smex]);

  const editData = React.useCallback(({ data, token, iframeWrapper, multiple }) => {
    // cleanup any previously open session
    smex.endSession();
    
    return smex.editDocumentData({
      session: {
        multiple,
        sessionAuthToken: token,
        mountNode: iframeWrapper,
        closeOnComplete: true,
      },
      data,
    });
  }, [smex]);

  return {
    extractDocument,
    editData,
    endSession,
  };
}

Last updated