CloudIO Platform
cloudio.ioVersion 3.0 Docs
  • CloudIO Platform
  • Architecture
  • Service Architecture
  • Scalability
  • Installation
  • Getting Started
    • Overview
    • How Tos
  • UI
    • App Controller
    • Page Controller
    • Controller Component
    • Custom Component
      • Sample Property Definitions
      • Custom Component Types
  • DataSource
    • Server Side Scripts
      • Sample Scripts
      • Module Imports
    • WHO Columns
  • REST APIs
    • Authentication
    • Query
    • Post
    • Status
    • API Playground
  • Workflow REST APIs
    • Introduction
    • PUT
    • GET
    • Instance PUT
    • Instance GET
    • Increment and GET
    • Instance Increment and GET
  • App Deployment
    • CloudIO CLI
    • Patch Management
    • SQL Migrations
    • Component Help
    • Email Setup
    • Configure SSO/OAuth
      • OAUTH 2.0
        • GOOGLE
      • SAML
        • AUTH0
        • AZURE AD
        • OKTA
      • Auto User Creation
    • Test Automation
    • On Premise Agent
  • Oracle Instant client
    • Setup
Powered by GitBook
On this page

Was this helpful?

Edit on GitHub
  1. UI

Controller Component

Controller Component can be used to create a page level custom component (one time) for some advanced use cases. The below example controller code exports a Controller Component named QuickEntry that renders couple quick entry input fields that makes parallel async calls to cloud functions and create records on tab out enabling users to perform high speed data entry.

Page Controller
import type { Store, BaseFunctionProps } from 'cloudio';
import { useStringAttribute, useNumberAttribute } from 'cloudio';
import { OmsPreOrderLines } from '@cloudio-saas/datasource-types';
import React, { useRef } from 'react';
import { Box, TextField } from '@mui/material';
import platform from 'platform';

async function createOrUpdateLine(
  linesStore: Store<OmsPreOrderLines>,
  id: string,
  resp: OmsPreOrderLines,
): Promise<string> {
  if (id) {
    // update record
    linesStore.updateRecord(id, resp);
  } else {
    // create record
    const newid = await linesStore.createNew({
      partialRecord: resp,
      addOnTop: true,
      rs: 'I',
    });
    if (!newid) {
      throw new Error('Failed to create new record!');
    }
    id = newid;
  }
  return id;
}

async function onQuickEntryQtyChange({
  appUid,
  pageId,
  itemId,
  platform,
}: BaseFunctionProps) {
  // get the stores
  const quickEntryStore = platform.getStore<OmsPreOrderLines>(
    appUid,
    pageId,
    'quickEntryAlias',
  );
  const linesStore = platform.getStore<OmsPreOrderLines>(
    appUid,
    pageId,
    'omsPreOrderLinesAlias',
  );
  if (!quickEntryStore || !linesStore) {
    platform.showError(`Store not found for ${itemId}`);
    return;
  }
  // get the current quick entry row
  const quickRow = quickEntryStore.getCurrentRecord();
  const { itemCode, itemQty } = quickRow;
  quickEntryStore.clearQuietyly().then(() => {
    quickEntryStore.createNew({ partialRecord: {}, rs: 'N' });
  });
  let id = '';
  // invoke cloud functions in parallel
  await Promise.all([
    platform
      .invokeCloudFunction(appUid, 'get-oms-item-details', {
        itemCode,
        itemQty,
      })
      .then(async (resp: OmsPreOrderLines) => {
        const { itemCode, itemQty, itemDesc } = resp;
        id = await createOrUpdateLine(linesStore, id, {
          itemCode,
          itemQty,
          itemDesc,
        });
        platform.redrawCanvasGrid(appUid, pageId, 'canvasGrid');
      }),
    platform
      .invokeCloudFunction(appUid, 'get-oms-item-price', { itemCode, itemQty })
      .then(async (resp: OmsPreOrderLines) => {
        const { sellPrice } = resp;
        id = await createOrUpdateLine(linesStore, id, {
          itemCode,
          itemQty,
          sellPrice,
        });
        platform.redrawCanvasGrid(appUid, pageId, 'canvasGrid');
      }),
  ]);
}

function QuickEntry(props: BaseFunctionProps) {
  // similar to useState hook in react for an attribute in the current record
  const [itemCode, setItemCode] = useStringAttribute('itemCode');
  const [itemQty, setItemQty] = useNumberAttribute('itemQty');
  // ref used for focus
  const ref = useRef<HTMLInputElement>(null);
  // ref to store the focus value
  const focusVal = useRef<number | undefined>(undefined);

  return (
    <Box sx={{ flex: 1, display: 'flex', minWidth: '400px', gap: '8px' }}>
      <TextField
        inputRef={ref}
        variant="standard"
        label="Item Code"
        value={itemCode ?? ''}
        onChange={(e) => {
          setItemCode(e.target.value);
        }}
        fullWidth
      />
      <TextField
        type="number"
        variant="standard"
        label="Item Qty"
        value={itemQty ?? ''}
        onChange={(e) => {
          let val: number | undefined = Number(e.target.value);
          if (Number.isNaN(val)) {
            val = undefined;
          }
          setItemQty(val);
        }}
        onFocus={() => {
          // store the existing value, so we can check against this in onBlur
          focusVal.current = itemQty;
        }}
        onBlur={(e) => {
          if (focusVal.current !== itemQty) {
            // value changed, create line
            onQuickEntryQtyChange(props);
            ref.current?.focus();
          }
        }}
        fullWidth
      />
    </Box>
  );
}

// must export a default object with all the functions to be used by this page
export default {
  QuickEntry,
};
PreviousPage ControllerNextCustom Component

Last updated 2 years ago

Was this helpful?