Skip to content

lib-finStackMobile 库参考 ​

原文: https://finproducts.atlassian.net/wiki/spaces/JIDD3/pages/34793325265/FIN+5.3.1+lib-finStackMobile 中文整理基于 FIN 5.3.1

导读: 本页为 lib-finStackMobile 的 API / 标签 / 函数参考文档。

以下为 API 参考,保留英文以便对照源码;目录已列出(英文标题便于检索);概述已尽量中译。


目录(导读) ​

  • lib
  • meta
  • tags
  • funcs
  • def
  • supertypes
  • tags
  • alarmsV2Menu()
    • src
  • blineMenu()
  • cleanFolderPathName(stringToClean)
  • commonTagBundles()
  • comparePointVal(equipId, pointName: "Room Setpoint")
  • connectorPoinBadgeVal(item)
  • connectorPointBadgeType(item)
  • connectorPointColor(item)
  • connectorPointTooltip(item)
  • connectorSelectedMenu(id, connType: null)
  • connectorsByTypeMenu(type)
  • connectorsDebugInfoMenu(connId)
  • connectorsMainMenu()
  • connectorsMenu(targetRef: null, viewAll: false)
  • connectorsMenuSettings(viewAll: false)
  • connectorsPointIcons(item)
  • connectorsPolicyInfo(id)
  • connectorsRightIcon(connector)
  • connectorsShowPoints(id, path: null)
  • connectorsTunePolicyMenu()
  • dbAddEditCommit(recId: null, props, folderPath: null, emptyFolderId: null)
  • dbBuilderCreateLearnPointsJob(connRef, connType: "bacnet", learnPath: null)
  • dbBuilderDiscoverBacnetPoints(connRef, jobRec, folder: null)
  • dbBuilderDiscoverConnectors(discoverId: null, connType: "bacnet", useConnDiscover: false)
  • dbBuilderDropAction(dragTargets, dropTarget, treeType: "")
  • dbBuilderSelectAction(panelOpts, selectedRef: null)
  • dbDiscoveryAdd(connectors, makeTemplate: false, refreshStr: "")
  • dbDragActionAddConnector(dropTarget, dragItems, targetRef: null)
  • dbGraphicPanels(nodeId, treeType: "")
  • dbMakeDataGridPanel(panelFilter, type: "equip", folderPath: "", navNameForDis: true, hiddenCols: [])
  • dropActionConnectorTree(dragTargets, dropTarget)
  • dropActionEquipTree(dragTargets, dropTarget, haystackConnRef: null)
  • dropActionFolderPaths(dragTargets, dropTarget, treeTag)
  • dropActionSavedFiltersTree(dragTargets, dropTarget)
  • dropActionScheduleTree(dragTargets, dropTarget, connRefTag: null)
  • dropActionTagBundlesTree(dragTargets, dropTarget, jsAction: [])
  • finAddBuilderProps(treeDataGrid, treeDis, branchDis)
  • finAddPointInfo(newRefs)
  • finAlarmSettingsForm(pollRate: 0, disableNotifications: true)
  • finApplyTagBundle(tagBundles, targetFilter, customTags: [], unapply: false)
  • finBackupRecordForm(selected: null)
  • finBackupUploadForm(selected: null)
  • finBlocks()
  • finBlocksJavaScript()
  • finBlocksPpcl()
  • finBreadcrumbs(treeType: "equip", targetRef: null, maxLevels: null)
  • finBuilderContextMenuItems()
  • finBuilderEquipTrash(recs)
  • finClimbNavTree(curType, targetRef)
  • finCommonQueries()
  • finConstructBasicTreeItem(record, treeDis, branchDis, treeInfo)
  • finContentOnFunc(target: null)
  • finCreateFolder(folderName, treeTag, parentFolderPath: null, childId: null)
  • finCreateFolderPath(id: null, filterFor)
  • finCreateProjectForm(preFill: null)
  • finDBCreateNewEquipCommit(equipName, navKind, parent: null, pointSettings: null)
  • finDbBuilderMenuItem()
  • finDbHaystackFindUniqueEquipTypes(conn, filter, percentMatch, applyTags, tag)
  • finDbHaystackNodeSelectAction(queryStr, nodeTypeStr)
  • finDbHaystackReadAllPoints(connectorRef, branchFilter, iteration)
  • finDbRelationshipAddEdit(curItem: null, folderPath: null)
  • finDbSavedFiltersTreeSelectAction(selectedRef: "")
  • finDbSavedQueryFilterAddEdit(curItem: null, folderPath: null)
  • finDbTagBundleAddEdit(curItem: null, folderPath: null)
  • finDbTemplateAddEdit(curItem: null, folderPath: null)
  • finDbTopicAdd(folderPath: null)
  • finEquipCharts(equ, rng: today)
  • finEquipRefTree(id, treePath: null)
  • finExtSettingsForm(data: null)
  • finFavoritesForm(newnotremove: true, url: null, data: null)
  • finFavoritesMenu(target: null)
  • finFindNonDbRec(listOfIds)
  • finFindToolsOnNavItem(navItemRefs: null)
  • finFolioDownloadForm(data: null, app: null)
  • finFolioMenu()
  • finFolioSettings(stage, inp: null)
  • finFolioUploadForm(stage: null, data: null, app: null)
  • finFormAddEditHaystackConnector(haystackConnRef: null, refill: null, folderPath: null)
  • finFormBacnetConnDiscoverSettings(refill: null)
  • finFormCloneConnector(selectedTargets, curType: "bacnet", curContext: null, reopen: false, jsAction: "")
  • finFormConfirmChangesAlert(action, msg, jsAction: "")
  • finFormDBAddEdit(treeType, edit: null, refill: null, folderPath: null, refreshTop: false, haystackRef: null, isConn: false)
  • finFormDBBuilderDelete(selectedItem, customAction: null, customMsg: null, itemTree: null, folderPath: "")
  • finFormDBCreateNewEquip(parentNav, parentId: null, equipNav: "", reopen: false)
  • finFormDBSelectEditDelete(details, folderPath: "", targetRef: null)
  • finFormEditSchedule(id: null, folderPath: null)
  • finFormManualAddEditBacnet(curConn: null, refill: null, connType: "ip", folderPath: null)
  • finFormManualOverrideAuto(targetRef, autoAll: true, level: 8)
  • finFormNewHaystackPassword(haystackConnRef, changesDict)
  • finFormRunToolsOnMulti(id, reopened: false)
  • finFormSchedulePointPriority(ids, prio: null)
  • finFormSelectBacnetType(folderPath: null)
  • finFormSelectTool(id, selected, advanced, reopened: false)
  • finFormSetConnectorDefWriteLevel(connectorIds: [])
  • finFormSetSummaryPointOrder(summaryName, summariesToRunOn: null, pointsInEquip: null, equipFilter: null)
  • finGetPods(podName)
  • finGetPointIcon(rec)
  • finGetTileOn(floor)
  • finGraphicTopLevel(new, data: null)
  • finGraphicTopLevelDeleteConfirmForm(graphicId, targetRef: null)
  • finGraphicsGenericBindings(glist, type)
  • finGraphicsGenericBindingsForm(tref: null)
  • finGraphicsGenericBindingsResults(fail)
  • finGraphicsUpdateThumbs(stage: null, data: null)
  • finHasSpecialChars(stringToCheck)
  • finHeaderAddEditMenu(idnex: null)
  • finHeaderAddEditSubMenu(parnt: null, idnex: null)
  • finHeaderButtonBadgeForm(parnt, child: null)
  • finHeaderButtonIconForm(parnt, child: null, data: null)
  • finHeaderButtonLinkForm(parnt, child: null, data: null)
  • finHeaderButtonNameForm(parnt, child: null)
  • finHeaderButtonSecurityForm(parnt, child: null)
  • …(其余标题见英文正文)

概述(中译) ​

FIN 堆栈应用程序用户界面


API 正文(英文) ​

tags ​

finDropOverrideFeature namespace of definitions formatted as feature:name
finInteractionMap of name/value tag pairs

funcs ​

alarmsV2MenuAxon function
blineMenuAxon function
cleanFolderPathNameAxon function
commonTagBundlesAxon function
comparePointValAxon function
connectorPoinBadgeValAxon function
connectorPointBadgeTypeAxon function
connectorPointColorAxon function
connectorPointTooltipAxon function
connectorSelectedMenuAxon function
connectorsByTypeMenuAxon function
connectorsDebugInfoMenuAxon function
connectorsMainMenuAxon function
connectorsMenuAxon function
connectorsMenuSettingsAxon function
connectorsPointIconsAxon function
connectorsPolicyInfoAxon function
connectorsRightIconAxon function
connectorsShowPointsAxon function
connectorsTunePolicyMenuAxon function
dbAddEditCommitAxon function
dbBuilderCreateLearnPointsJobAxon function
dbBuilderDiscoverBacnetPointsAxon function
dbBuilderDiscoverConnectorsAxon function
dbBuilderDropActionAxon function
dbBuilderSelectActionAxon function
dbDiscoveryAddAxon function
dbDragActionAddConnectorAxon function
dbGraphicPanelsFunction returns a list of graphics whose graphicOns evaluate to nodeId
dbMakeDataGridPanelConstructs a basic grid panel to be used with the DB Builder app
dropActionConnectorTreeAxon function
dropActionEquipTreeDetermines and takes the appropriate action for when an item is dropped onto an item within the equip tree in the DB Builder app
dropActionFolderPathsAxon function
dropActionSavedFiltersTreeDetermines and takes the appropriate action for when an item is dropped onto an item within the saved filter tree in the DB Builder app
dropActionScheduleTreeDetermines and takes the appropriate action for when an item is dropped onto an item within the schedule tree in the DB Builder app
dropActionTagBundlesTreeDetermines and takes the appropriate action for when an item is dropped onto an item within the tagBundle tree in the DB Builder app
finAddBuilderPropsAxon function
finAddPointInfoAxon function
finAlarmSettingsFormAxon function
finApplyTagBundleApplies the passed tagBundles addTags and removeTags properties to the targetFilter that fits a tagBundle's allowFilter
finBackupRecordFormAxon function
finBackupUploadFormAxon function
finBlocksThis function uses the blocks() function to gather all blocks and then adds additional information too each block specific to FIN Stack
finBlocksJavaScriptAxon function
finBlocksPpclAxon function
finBreadcrumbsAxon function
finBuilderContextMenuItemsAxon function
finBuilderEquipTrashAxon function
finClimbNavTreeAxon function
finCommonQueriesAxon function
finConstructBasicTreeItemAxon function
finContentOnFuncfinContentOn(Ref target
finCreateFolderAxon function
finCreateFolderPathAxon function
finCreateProjectFormAxon function
finDBCreateNewEquipCommitAxon function
finDbBuilderMenuItemAxon function
finDbHaystackFindUniqueEquipTypesAxon function
finDbHaystackNodeSelectActionAxon function
finDbHaystackReadAllPointsAxon function
finDbRelationshipAddEditAxon function
finDbSavedFiltersTreeSelectActionCreates panels to be displayed on when an item from the savedFilters tree is selected
finDbSavedQueryFilterAddEditAxon function
finDbTagBundleAddEditAxon function
finDbTemplateAddEditAxon function
finDbTopicAddAxon function
finEquipChartsFunction to generate chart for equip with schedules and alarms
finEquipRefTreeAxon function
finExtSettingsFormAxon function
finFavoritesFormAxon function
finFavoritesMenuAxon function
finFindNonDbRecReturns a list of dicts resembling, if not actually, records
finFindToolsOnNavItemAxon function
finFolioDownloadFormForm to download records with a certain filter, like legacy Folio Download
finFolioMenuAxon function
finFolioSettingsAxon function
finFolioUploadFormForm to upload records through file or through text, like legacy Folio Import
finFormAddEditHaystackConnectorAxon function
finFormBacnetConnDiscoverSettingsAxon function
finFormCloneConnectorAxon function
finFormConfirmChangesAlertCreates a basic form with "Warning" as the form title, a "Cancel" button, and an "Apply" button
finFormDBAddEditA form used to create or edit DB Builder items
finFormDBBuilderDeleteAxon function
finFormDBCreateNewEquipAxon function
finFormDBSelectEditDeleteAxon function
finFormEditScheduleForm to edit schedules
finFormManualAddEditBacnetAxon function
finFormManualOverrideAutoAxon function
finFormNewHaystackPasswordAxon function
finFormRunToolsOnMultiAxon function
finFormSchedulePointPriorityAxon function
finFormSelectBacnetTypeAxon function
finFormSelectToolAxon function
finFormSetConnectorDefWriteLevelAxon function
finFormSetSummaryPointOrderAxon function
finGetPodsAxon function
finGetPointIconReturns the name of the appropriate point icon based off the point's type
finGetTileOnAxon function
finGraphicTopLevelfinGraphicTopLevel(new) Form to create or edit the topLevel record
finGraphicTopLevelDeleteConfirmFormAxon function
finGraphicsGenericBindingsAxon function
finGraphicsGenericBindingsFormAxon function
finGraphicsGenericBindingsResultsAxon function
finGraphicsUpdateThumbsForm to change the thumbnails on graphics
finHasSpecialCharsAxon function
finHeaderAddEditMenuAxon function
finHeaderAddEditSubMenuAxon function
finHeaderButtonBadgeFormAxon function
finHeaderButtonIconFormAxon function
finHeaderButtonLinkFormAxon function
finHeaderButtonNameFormAxon function
finHeaderButtonSecurityFormAxon function
finHeaderFormAxon function
finHeaderFuncsBackend functions for finHeaderForm function
finHeaderHomeFormAxon function
finHeaderMenuAxon function
finHeaderReorderFuncAxon function
finHeaderReorderMenuAxon function
finHeaderReorderSubMenuAxon function
finHostChangePassFormAxon function
finHostMainMenuAxon function
finHostUpdateLicenseFormAxon function
finHostUsageFormAxon function
finInfoMenuAxon function
finInjectableProgramResourcesAxon function
finJobMenuAxon function
finJobSettingsAxon function
finManualAddEditBacnetCommitAxon function
finMobileHardDeleteAxon function
finNavListChildrenAxon function
finNavTreeDropOverridesAxon function
finNavTreeTypesAxon function
finOMAddFormAxon function
finOMContentOnFormAxon function
finOMDeleteFormAxon function
finOMMenuAxon function
finOMMenu2Axon function
finOMMenu3Axon function
finProjectAuditFormAxon function
finProjectCategoryFormAxon function
finProjectEmailFormAxon function
finProjectProjectFormAxon function
finQueriesAxon function
finReadByIdTrashAxon function
finReadByIdsTrashAxon function
finReadCsvWithEmbeddedDelimeterAxon function
finReadHeaderfinReadHeader() Returns content of finHeader record
finRestartFinstackAxon function
finRunSelectedToolAxon function
finSettingsMenuAxon function
finSettingsMenuLegacyAxon function
finStackMenuAllAxon function
finStackMenuAppListAxon function
finStackMenuApplySettingsAxon function
finStackMenuBackButtonAxon function
finStackMenuFolderPathAxon function
finStackMenuInsertVarAxon function
finStackMenuOkFormAxon function
finStackMenuOpenNewAxon function
finStackMobileMenuAxon function
finSummaryDeleteFormAxon function
finSummaryJsonreturns a JSON object
finSummaryMenuAxon function
finSyncHisFormAxon function
finTraceSubEquipAxon function
finUniversalServiceRestartAxon function
finValidateEmailReturns true if email is in the form [userName]@[domain].[topLevelDomain] and returns false if not
finWeatherMenuAxon function
findEquipTreeAddOptsAxon function
folderPathDeleteAxon function
folderPathEditAxon function
folderPathMoveAxon function
folioDebugQueryFormAxon function
folioDebugTagFormAxon function
folioDebugWatchesFormAxon function
folioFileAddTagFormAxon function
folioFileBatchTrashFormAxon function
folioFileEditFormAxon function
folioFileTrashFormAxon function
folioFileUploadFormAxon function
folioOrphanCleanupAxon function
folioOverwriteFileCommitAxon function
folioOverwriteFileFormAxon function
folioQueryFormAxon function
folioQueryMenuAxon function
folioQueryViewFormAxon function
folioSnapRestoreProgBarAxon function
folioSnapRestoreRestartAxon function
folioSnapUploadFormAxon function
folioTrashDeleteFormAxon function
folioTrashEmptyFormAxon function
folioTrashRestoreFormAxon function
folioTrashViewFormAxon function
getEnumAlarmTextAxon function
graphicsBuilderNewAxon function
graphicsMenuAxon function
graphicsMenuSettingsAxon function
graphicsMobileMenuAxon function
graphicsSelectedMenuAxon function
graphicsVirtPtIconAxon function
graphicsVirtPtIconColorAxon function
infoInfoFormAxon function
infoLintFormAxon function
infoReportFormAxon function
infoThreadsFormAxon function
infoViewerLibsFormAxon function
jobAppConfigAxon function
jobCreateFormAxon function
jobDebugFormAxon function
jobEditFormAxon function
jobFinBackupAxon function
jobParseTimeAxon function
jobRunFormAxon function
jobTrashFormAxon function
manualOverrideArrayMenuAxon function
manualOverrideMenuAxon function
manualOverridesMainMenuAxon function
menuForButtonAxon function
menuForLabelAxon function
menuForProgramAxon function
menuForSupermanAxon function
menuForVirtualPointAxon function
mobileViewRecordAddAxon function
mobileViewRecordEditAxon function
mobileViewRecordInfoMenu to view tags of a record
mobileViewRecordStringAxon function
nextActionProgramBlockTreeAxon function
nextActionProgramBlockTree2Axon function
nextActionProgramTreeAxon function
nextActionProgramTree2Axon function
priorityBadgeValAxon function
scheduleBadgeTipAxon function
scheduleBadgeTypeAxon function
scheduleBadgeValAxon function
scheduleCreateNewCommitAxon function
scheduleCreateNewDefValAxon function
scheduleCreateNewFormAxon function
scheduleDisplayAxon function
scheduleFindPointsAxon function
scheduleFindPointsCommitAxon function
scheduleGetRefsAxon function
scheduleIconTipAxon function
scheduleMenuAxon function
scheduleMenuSettingsAxon function
scheduleMoveSchedulableAxon function
scheduleToolTreeFormAxon function
scheduleToolTreeFormCommitAxon function
selectActionDiscoverAxon function
selectActionEquipTreeCreates panels to be displayed on when an item from the equip tree is selected
selectActionGraphicsTreeAxon function
selectActionJobTreeAxon function
selectActionProgramCatTreeAxon function
selectActionProgramCatTree2Axon function
selectActionProgramTasksTreeAxon function
selectActionProgramTreeAxon function
selectActionProgramVarBindingsTreeAxon function
selectActionScheduleTreeAxon function
selectActionScheduleTree2Axon function
selectActionTagBundlesTreeAxon function
userDeleteConfirmAxon function
userFormSetPasswordAxon function
usersAccessFilterWizardAxon function
usersEditUsernameFormAxon function
usersFormAppPermissionsAxon function
usersFormAppPermissionsCommitAxon function
usersFormCloneAxon function
usersFormCloneCommitAxon function
usersFormCreateNewAxon function
usersFormCreateNewCommitAxon function
usersFormCreateNewOptionsAxon function
usersFormEditAxon function
usersFormEditCommitAxon function
usersFormSelectEditAxon function
usersFormSubscriptionsAxon function
usersFormSubscriptionsCommitAxon function
usersInputValidatorAxon function
usersMainMenuSettingsAxon function
usersRunToolAxon function
usersToolSettingsAxon function
usersTypeAxon function
weatherFormAxon function


def ​

finDropOverride ​

Feature namespace of definitions formatted as feature:name


meta ​

deffinDropOverride
isfeature
liblib:finStackMobile

supertypes ​

featureFeature namespace of definitions formatted as feature:name

tags ​

finInteractionMap of name/value tag pairs


def ​

finInteraction ​

Map of name/value tag pairs. See Kinds chapter.


meta ​

deffinInteraction
isdict
liblib:finStackMobile
tagOnfinDropOverride

supertypes ​

valData value type
dictMap of name/value tag pairs


def ​

func:alarmsV2Menu ​

alarmsV2Menu() ​

Axon function


meta ​

deffunc:alarmsV2Menu
finStackMobileMenu✓
isfunc
liblib:finStackMobile
namealarmsV2Menu
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

() => do
  [{
    displayName: toLocale("finStackMobileExt::rightMenuAlarmsTitle"),
    link: "",
    appId: "alarms",
    extName: "alarm",
    icon: "icon-volume-full",
    iconType: "class",
    hasBadge: false,
    action: "window.app.LoadApplication('/pod/finAlarms/dist/index.html', null, null, {app: '_alarms', params: []})",
    level: 0,
    ui: "html",
    minUiTarget: "phone",
    order: 1
  }]
end


def ​

func:blineMenu ​

blineMenu() ​

Axon function


meta ​

deffunc:blineMenu
finStackMobileMenu✓
isfunc
liblib:finStackMobile
nameblineMenu
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

() => do
  numPrograms: secureReadAll(program).size

  settings: {
    funcCall: "blineMainMenu({{targetRef}})",
    folderPath:"",
    display: "name",
    icon: "icon-code",
    hasBadge: true,
    badgeValueFunc: "blineBadgeVal()",
    badgeTypeFunc: "blineBadgeType()",
    folderPathCount:0,
    badgeTooltip: toLocale("finStackMobileExt::toolTipTasksAssigned"),
    folderBadge: "programs",
    hideBackButton: true,
    keepOpen:true,
    topItemsIgnorePaginate: 5,
    //paginateCount: 1
  }

  pointVars: ()=>{
    items: [{
      label: toLocale("finStackMobileExt::bLineNew"),
      icon: "icon-plus",
      tooltip: toLocale("finStackMobileExt::makeNewProg"),
      action: "finstack.eval('blineCreateNewProgForm({{targetRef}})')",
      keepOpen: true
    }, {
      label: toLocale("finStackExt::programs"),
      icon: "icon-link",
      tooltip: toLocale("finStackMobileExt::viewPrograms"),
      action: "window.app.ObtainMenu(null, null,'bline', "+ settings.toAxonCode +")",
      keepOpen: true }
  ]}.toJSON()

  [{
      displayName: toLocale("finStackMobileExt::rightMenuLogicBuilder"),
      link: "",
      appId: "bline",
      extName: "finBlockProgramming",
      icon: "icon-network-2",
      iconType: "class",
      hasBadge: true,
      badgeValue: numPrograms,
      badgeType: "normal",
      badgeTooltip: numPrograms + " "+toLocale("finStackExt::programs"),
      action: "null",
      submenu: pointVars(),
      level: 0,
      ui: "html",
      classes:"tablet-only-hidden mobile-hidden",
      keepOpen:true,
      order: 104,
      hyperlinkAct:"window.app.ObtainMenu(null, null,'bline', "+ settings.toAxonCode +")"
    }]

end


def ​

func:cleanFolderPathName ​

cleanFolderPathName(stringToClean) ​

Axon function


meta ​

deffunc:cleanFolderPathName
isfunc
liblib:finStackMobile
namecleanFolderPathName
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function


def ​

func:commonTagBundles ​

commonTagBundles() ​

Axon function


meta ​

deffunc:commonTagBundles
isfunc
liblib:finStackMobile
namecommonTagBundles
overridable✓
private✓
tagBundleFunc✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

() => do
  [
    {
      id: @tagBundle:numericAlarms,
      dis: toLocale("finStackMobileExt::tagBundle.numberAlarms.dis"),
      name: "numericAlarms",
      addTags: "allowProgram,timer:60",
      description: toLocale("finStackMobileExt::tagBundle.numberAlarms.tooltip"),
      allowFilter: "(point and kind==\"Number\")",
      folderPath: "/" + toLocale("finStackMobileExt::rightMenuAlarmsTitle"),
      order: 1,
      tagBundle
    },

    {
      id: @tagBundle:booleanAlarm,
      dis: toLocale("finStackMobileExt::tagBundle.boolAlarms.dis"),
      name: "booleanAlarm",
      addTags: "alarmPoint,allowProgram,alarmEnable:true,alarmText:\"Point is in alarm state\",boolAlarmState:true,alarmDelay:0s,alarmPriority:0",
      allowFilter: "point and kind==\"Bool\"",
      description: toLocale("finStackMobileExt::tagBundle.boolAlarms.tooltip"),
      folderPath: "/" + toLocale("finStackMobileExt::rightMenuAlarmsTitle"),
      pointKind: "Bool",
      removeTags: "",
      tagBundle,
      trackBundle,
      alarmConfig
    },

    {
      id: @tagBundle:imperialToMetric,
      dis: toLocale("finStackMobileExt::tagBundle.impToMetric.dis"),
      name: "imperialToMetric",
      addTags: "{{ImperialToMetric(row->id)}}",
      description: toLocale("finStackMobileExt::tagBundle.impToMetric.tooltip"),
      allowFilter: "(point and kind==\"Number\")",
      folderPath: "/" + toLocale("finStackMobileExt::conversion"),
      order: 1,
      tagBundle
    },

    {
      id: @tagBundle:stringAlarms,
      dis: toLocale("finStackMobileExt::tagBundle.stringAlarms.dis"),
      name: "stringAlarms",
      addTags: "allowProgram,timer:60",
      description: toLocale("finStackMobileExt::tagBundle.stringAlarms.tooltip"),
      allowFilter: "(point and kind==\"Str\")",
      folderPath: "/" + toLocale("finStackMobileExt::rightMenuAlarmsTitle"),
      order: 3,
      tagBundle
    },

    {
      id: @tagBundle:invertCurVal,
      dis: toLocale("finStackMobileExt::tagBundle.invertCur.dis"),
      name: "invertCurVal",
      addTags: "curConvert:\"invert()\"",
      description: toLocale("finStackMobileExt::tagBundle.invertCur.tooltip"),
      allowFilter: "point",
      folderPath: "/" + toLocale("finStackMobileExt::conversion"),
      order: 3,
      tagBundle
    },

    {
      id: @tagBundle:metricToImperial,
      dis: toLocale("finStackMobileExt::tagBundle.metricToImp.dis"),
      name: "metricToImperial",
      addTags: "{{metricToImperial(row->id)}}",
      description: toLocale("finStackMobileExt::tagBundle.metricToImp.tooltip"),
      allowFilter: "(point and kind==\"Number\")",
      folderPath: "/" + toLocale("finStackMobileExt::conversion"),
      order: 2,
      tagBundle
    },

    {
      id: @tagBundle:removeWritable,
      dis: toLocale("finStackMobileExt::tagBundle.removeWrite.dis"),
      name: "removeWritable",
      removeTags: "-haystackWriteLevel,-haystackWrite,-bacnetWriteLevel,-bacnetWrite,-writeLevel,-actions,-writable,-curTracksWrite",
      description: toLocale("finStackMobileExt::tagBundle.removeWrite.tooltip"),
      allowFilter: "point",
      folderPath: "/" + toLocale("finStackMobileExt::writable"),
      order: 1,
      tagBundle
    },

    {
      id: @tagBundle:addWritableBacnet,
      dis: toLocale("finStackMobileExt::tagBundle.addWriteBacnet.dis"),
      name: "addWritableBacnet",
      addTags: "bacnetWrite:@null,bacnetWriteLevel:16,writable,{{addBacnetActions(row->id)}},{{copyCurToWriteBacnet(row->id)}}",
      description: toLocale("finStackMobileExt::tagBundle.addWriteBacnet.tooltip"),
      allowFilter: "point and bacnetConnRef",
      folderPath: "/" + toLocale("finStackMobileExt::writable"),
      order: 2,
      tagBundle
    },

    {
      id: @tagBundle:addWritableHaystack,
      dis: toLocale("finStackMobileExt::tagBundle.addWriteHaystack.dis"),
      name: "addWritableHaystack",
      addTags: "haystackWrite:@null,haystackWriteLevel:16,writable,{{addHaystackActions(row->id)}},{{copyCurToWriteHaystack(row->id)}}",
      description: toLocale("finStackMobileExt::tagBundle.addWriteHaystack.tooltip"),
      allowFilter: "point and haystackConnRef",
      folderPath: "/" + toLocale("finStackMobileExt::writable"),
      order: 3,
      tagBundle
    },

    {
      id: @tagBundle:numericHisInterval,
      dis: toLocale("finStackMobileExt::tagBundle.numberInterval.dis"),
      name: "numericHisInterval",
      addTags: "his,hisCollectInterval:15min",
      removeTags: "-haystackHis,-bacnetHis",
      description: toLocale("finStackMobileExt::tagBundle.numberInterval.tooltip"),
      allowFilter: "(point and kind==\"Number\")",
      folderPath: "/" + toLocale("finStackMobileExt::histories"),
      order: 1,
      tagBundle
    },

    {
      id: @tagBundle:numericHisCov,
      dis: toLocale("finStackMobileExt::tagBundle.numberIntervalCov.dis"),
      name: "numericHisCov",
      addTags: "his,hisCollectInterval:15min, hisCollectCov:5",
      removeTags: "-haystackHis,-bacnetHis",
      description: toLocale("finStackMobileExt::tagBundle.numberIntervalCov.tooltip"),
      allowFilter: "(point and kind==\"Number\")",
      folderPath: "/" + toLocale("finStackMobileExt::histories"),
      order: 2,
      tagBundle
    },

    {
      id: @tagBundle:boolHis,
      dis: toLocale("finStackMobileExt::tagBundle.boolInterval.dis"),
      name: "boolHis",
      addTags: "his,hisCollectInterval:24hr,hisCollectCov",
      removeTags: "-haystackHis,-bacnetHis",
      description: toLocale("finStackMobileExt::tagBundle.boolInterval.tooltip"),
      allowFilter: "(point and kind==\"Bool\")",
      folderPath: "/" + toLocale("finStackMobileExt::histories"),
      order: 3,
      tagBundle
    },

    {
      id: @tagBundle:enumAlarm,
      name: "enumAlarm",
      dis: toLocale("finStackMobileExt::tagBundle.enumAlarms.dis"),
      addTags: "alarmPoint,allowProgram,alarmEnable:true,alarmText:\"Point is in an alarm state\",alarmStateText:\"protect;economy\",alarmDelay:0s,alarmPriority:100",
      allowFilter: "point and enum and kind==\"Str\"",
      description: toLocale("finStackMobileExt::tagBundle.enumAlarms.tooltip"),
      folderPath: "/" + toLocale("finStackMobileExt::rightMenuAlarmsTitle"),
      pointKind: "Enum",
      removeTags:"",
      tagBundle,
      trackBundle,
      alarmConfig
    },

    {
      id: @tagBundle:highLimitAlarm,
      dis: toLocale("finStackMobileExt::tagBundle.highLimit.dis"),
      name: "highLimitAlarm",
      addTags: "alarmPoint,allowProgram,alarmEnable:true,alarmText:\"Point is too high\",highLimit:80,alarmDelay:0s,alarmPriority:100",
      allowFilter: "point and kind==\"Number\"",
      description: toLocale("finStackMobileExt::tagBundle.highLimit.tooltip"),
      folderPath: "/" + toLocale("finStackMobileExt::rightMenuAlarmsTitle"),
      pointKind: "Number",
      removeTags:"",
      tagBundle,
      alarmConfig,
      trackBundle
    },

    {
      id: @tagBundle:deltaFromSetpoint,
      dis: toLocale("finStackMobileExt::tagBundle.deltaSetpoint.dis"),
      name: "deltaFromSetpoint",
      addTags: "alarmPoint,allowProgram,dAlarmEnable:true,dAlarmText:\"Point is outside +/- deltaLimit\",deltaLimit:4,dAlarmDelay:0s,dAlarmPriority:100,comparePointName:\"Setpoint\"",
      allowFilter: "point and kind==\"Number\"",
      description: toLocale("finStackMobileExt::tagBundle.deltaSetpoint.tooltip"),
      folderPath: "/" + toLocale("finStackMobileExt::rightMenuAlarmsTitle"),
      pointKind: "Number",
      removeTags:"",
      tagBundle,
      alarmConfig,
      trackBundle
    },

    {
      id: @tagBundle:lowLimitAlarm,
      dis: toLocale("finStackMobileExt::tagBundle.lowLimit.dis"),
      addTags: "alarmPoint,allowProgram,llAlarmEnable:true,llAlarmText:\"Point is too low\",lowLimit:60,llAlarmDelay:0s,llAlarmPriority:100",
      allowFilter: "point and kind==\"Number\"",
      description: toLocale("finStackMobileExt::tagBundle.lowLimit.tooltip"),
      folderPath: "/" + toLocale("finStackMobileExt::rightMenuAlarmsTitle"),
      pointKind: "Number",
      removeTags:"",
      tagBundle,
      alarmConfig,
      trackBundle
    }
  ]
end


def ​

func:comparePointVal ​

comparePointVal(equipId, pointName: "Room Setpoint") ​

Axon function


meta ​

deffunc:comparePointVal
isfunc
liblib:finStackMobile
namecomparePointVal
overridable✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(equipId,pointName:"Room Setpoint") => do
  try read(equipRef==equipId and navName==pointName)->curVal
  catch null
end


def ​

func:connectorPoinBadgeVal ​

connectorPoinBadgeVal(item) ​

Axon function


meta ​

deffunc:connectorPoinBadgeVal
isfunc
liblib:finStackMobile
nameconnectorPoinBadgeVal
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(item) => do
  result: "null"

  if(item.has("curVal")) do
    if(item->kind == "Bool") do
      if(item.has("enum")) do
        if(item->curVal == false) result = item->enum.split(",")[0]
        else result = item->enum.split(",")[1]
      end else do
        if(item->curVal) result = "On"
        else result = "Off"
      end
    end else
      if(item.has("precision"))
        result = item->curVal.finPrecision(item->precision).toStr
      else
        result = item->curVal.toStr
  end

  result
end


def ​

func:connectorPointBadgeType ​

connectorPointBadgeType(item) ​

Axon function


meta ​

deffunc:connectorPointBadgeType
isfunc
liblib:finStackMobile
nameconnectorPointBadgeType
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(item) => do
  try do
    if(item->curStatus == "ok")
      return "success"
    else if(item->curStatus == "error" or item->curStatus == "fault" or item->curStatus == "down")
      return "error"
  end catch
    return "normal"
end


def ​

func:connectorPointColor ​

connectorPointColor(item) ​

Axon function


meta ​

deffunc:connectorPointColor
isfunc
liblib:finStackMobile
nameconnectorPointColor
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(item) => do
  try
    if(item->kind == "Number")
      return "item-numeric"
    else if(item->kind == "Bool")
      return "item-boolean"
    else if(item->kind == "Str" and item.has("enum"))
      return "item-enum"
    else
      return "item-string"
  catch ""
end


def ​

func:connectorPointTooltip ​

connectorPointTooltip(item) ​

Axon function


meta ​

deffunc:connectorPointTooltip
isfunc
liblib:finStackMobile
nameconnectorPointTooltip
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(item) => do
  tip: "curVal: "

  if(item.has("curVal"))
    tip = tip + item->curVal
  else
    tip = tip + "null"

  try tip = tip + ", curStatus: " + item->curStatus catch ""
end


def ​

func:connectorSelectedMenu ​

connectorSelectedMenu(id, connType: null) ​

Axon function


meta ​

deffunc:connectorSelectedMenu
isfunc
liblib:finStackMobile
nameconnectorSelectedMenu
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(id, connType: null) => do
  pointSettings: {
    funcCall: "connectorsShowPoints(@" + id + ")",
    display: "dis",
    hideBackButton: true,
    keepOpen: true,
    link: "#points?targetRef=@{equipRef}",
    iconFunc: "connectorsPointIcons()",
    iconType: "class",
    iconTooltipFunc: "dis",
    iconClassFunc: "connectorPointColor()",
    hasBadge: true,
    badgeValueFunc: "connectorPoinBadgeVal()",
    badgeTypeFunc: "connectorPointBadgeType()",
    badgeTooltipFunc: "connectorPointTooltip()",
    paginateCount: 100
  }

  if(connType == null) lst: finStackMenuBackButton(readById(id).dis, connectorsMenuSettings(), "connectors")
  else lst: finStackMenuBackButton(readById(id).dis, connectorsMenuSettings(true)
    .set("action", "openMenu:null, null, 'selectedConnector', {funcCall: 'connectorSelectedMenu(@*~id*, `"+ connType.toStr +"`)', header: '*~dis*', hideBackButton: true}")
    .set("funcCall","connectorsByTypeMenu('"+ connType.toStr +"')"), "connectors")

  lst.addAll([
    {displayName: "— "+toLocale("finStackExt::rightMenuConnectors")+" —", isHeader: true, isDivider: true, ignoreSettings, order: -9999},

    {
      displayName: toLocale("finStackMobileExt::addFolderPath"),
      appId: "addFolder",
      ignoreSettings,
      keepOpen: true,
      icon: "icon-plus",
      iconType: "class",
      action: "finstack.eval('finCreateFolderPath(" + id.toAxonCode + ",\"connState\")')",
      order: 2,
    },

    {
      displayName: toLocale("finStackExt::navMetaPoint"),
      link: "",
      appId: "connectorPoints",
      icon: "icon-folder",
      iconType: "class",
      action: "window.app.ObtainMenu(null, null, 'connectorPoints', " + pointSettings.toAxonCode + ")",
      level: 0,
      ui: "html",
      order: 2,
      //minUiTarget: "phone",
      keepOpen: true,
      ignoreSettings
    },
  ])

end


def ​

func:connectorsByTypeMenu ​

connectorsByTypeMenu(type) ​

Axon function


meta ​

deffunc:connectorsByTypeMenu
isfunc
liblib:finStackMobile
nameconnectorsByTypeMenu
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(type) => do
  finStackMenuBackButton(type, connectorsMenuSettings(), "connectors").addAll(eval("secureReadAll(" + type + ")").toRecList).add({displayName: "— "+toLocale("finStackExt::rightMenuConnectors")+" —", isHeader: true, isDivider: true, ignoreSettings, order: -9999})
end


def ​

func:connectorsDebugInfoMenu ​

connectorsDebugInfoMenu(connId) ​

Axon function


meta ​

deffunc:connectorsDebugInfoMenu
isfunc
liblib:finStackMobile
nameconnectorsDebugInfoMenu
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(connId) => do
  debugStats: finConnDebugInfo(connId, [connId], true)
  tempHolder: null
  pointSettings: {
    funcCall: "connectorsShowPoints(@" + connId + ")",
    display: "dis",
    hideBackButton: true,
    keepOpen: true,
    link: "#points?targetRef=@{equipRef}",
    iconFunc: "connectorsPointIcons()",
    iconType: "class",
    iconTooltipFunc: "dis",
    iconClassFunc: "connectorPointColor()",
    hasBadge: true,
    badgeValueFunc: "connectorPoinBadgeVal()",
    badgeTypeFunc: "connectorPointBadgeType()",
    badgeTooltipFunc: "connectorPointTooltip()",
    paginateCount: 100
  }

  statsList: finStackMenuBackButton(readById(connId).dis, pointSettings, "connectorPoints").add({
    displayName: "— "+toLocale("finStackExt::rightMenuConnectors")+" —",
    isHeader: true,
    isDivider: true,
    ignoreSettings,
    order: -9999
  })

  debugStats->debugInfo.split("\n").each x => do //.replace("] ", "]\n")
    tempHolder = x.split(":")
    if(tempHolder.size == 2 and tempHolder[1] != "")
      statsList = statsList.add({dis:tempHolder[0].trim + ": " + tempHolder[1].trim})
    else if(x.startsWith("uri:"))
      statsList = statsList.add({dis: "uri: " + x.replace("uri:", "").trim})
    else if(x.startsWith("Default"))
      statsList = statsList.add({dis: "pollBuckets: " + x})
  end

  statsList

end


def ​

func:connectorsMainMenu ​

connectorsMainMenu() ​

Axon function


meta ​

deffunc:connectorsMainMenu
finStackMobileMenu✓
isfunc
liblib:finStackMobile
nameconnectorsMainMenu
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

() => do
  numConns: 0

  finConnExts().finGridFilter(name != "finMail").colToList("tag").each type => do
    numConns = numConns + eval("secureReadAll(" + type + ").size")
  end

  [{
    displayName: toLocale("finStackExt::rightMenuConnectors"),
    link: "",
    appId: "connectorsApp",
    extName: "conn",
    icon: "icon-media-loop",
    iconType: "class",
    hasBadge: true,
    badgeType: "normal",
    badgeValue: numConns,
    classes:"tablet-only-hidden mobile-hidden",
    badgeTooltip: numConns + " "+toLocale("finStackExt::rightMenuConnectors"),
    action: "window.app.ObtainMenu(null, '{{targetRef}}','connectorsApp', "+ connectorsMenuSettings().toAxonCode +")",
    level: 0,
    ui: "html",
    order: 205,
    keepOpen:true
  }]

end


def ​

func:connectorsMenu ​

connectorsMenu(targetRef: null, viewAll: false) ​

Axon function


meta ​

deffunc:connectorsMenu
isfunc
liblib:finStackMobile
nameconnectorsMenu
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(targetRef:null, viewAll: false) => do
  settings: null
  menuItems: [{displayName: "— "+toLocale("finStackExt::rightMenuConnectors")+" —", isHeader: true, isDivider: true, ignoreSettings, order: -9999}]
  numberConns: 0
  numberPolicies: secureReadAll(connTuning).size
  equipSelected: false

  connTypes: finConnExts().finGridFilter(name != "finMail").colToList("tag")

  if(targetRef != null and readById(targetRef).has("equip") and not viewAll) do
    equipSelected = true
    totalNumConns: eval("secureReadAll(" + connTypes.concat(" or ") + ").size")

    menuItems = menuItems.add({
      displayName: toLocale("finStackMobileExt::viewAllConn"),
      ignoreSettings,
      appId: "allConns",
      icon: "icon-media-loop",
      iconType: "class",
      hasBadge: true,
      badgeValue: totalNumConns,
      badgeType: "normal",
      badgeTooltip: totalNumConns + " "+toLocale("finStackExt::rightMenuConnectors"),
      action: "window.app.ObtainMenu(null, '{{targetRef}}','allConns', "+ connectorsMenuSettings(true).toAxonCode +")",
      level: 0,
      order: -1020,
      ui: "html",
      keepOpen:true
    })
  end
  //go through each connectors by type and make a button to see only those type
  connTypes.each type => do
    numberConns: eval("secureReadAll(" + type + ").size")
    conns: []

    if(equipSelected and not viewAll) do
      tempHolder: eval("secureReadAll(" + type + "Ref and point and equipRef == " + targetRef.toAxonCode + ")")
      if(tempHolder.size > 0) do
        conns = tempHolder.unique(type + "Ref")
        conns = conns.map(row => readById(row[type + "Ref"]))
      end
      else numberConns = 0
    end

    settings = {
      funcCall: "connectorsByTypeMenu('" + type + "')",
      header: type[0..-5] + " "+toLocale("finStackExt::rightMenuConnectors"),
      folderPathCount: 0,
      icon: "icon-loading",
      iconType: "class",
      action: "openMenu:null, null, 'selectedConnector', {funcCall: 'connectorSelectedMenu(@*~id*, `"+ type +"`)', header: '*~dis*', hideBackButton: true}",
      hideBackButton: true,
      keepOpen: true,
      iconTooltip: "{uri}",
      rightIconFunc: "connectorsRightIcon()",
      rightIconType: "class",
      rightIconTooltip: "{connStatus}",
      folderBadge: "connectors"
    }

    //adds connectors matching the current type
    if(numberConns > 0) do
      menuItems = menuItems.add({
        displayName: type[0..-5].capitalize + " "+toLocale("finStackExt::rightMenuConnectors"),
        link: "",
        appId: type[0..-5].capitalize + toLocale("finStackExt::rightMenuConnectors"),
        icon: "icon-media-loop",
        iconType: "class",
        hasBadge: true,
        ignoreSettings: marker(),
        badgeValue: numberConns,
        badgeType: "normal",
        badgeTooltip: numberConns + " " + type[0..-5].capitalize + " "+toLocale("finStackExt::rightMenuConnectors"),
        action: "window.app.ObtainMenu(null, null,'" + type + "s" + "', "+ settings.toAxonCode +")",
        level: 0,
        order: -1015,
        ui: "html",
        keepOpen:true

      })

      if (equipSelected) menuItems = menuItems.addAll(conns.map(row => if(row.has("folderPath")) row.set("folderPath", row->folderPath.replace("/ ", "/")) else row).toRecList)
      else menuItems = menuItems.addAll(eval("secureReadAll(" + type + ")").map(row => if(row.has("folderPath")) row.set("folderPath", row->folderPath.replace("/ ", "/")) else row).toRecList)
    end
  end//end conenctors by type

  settings = {
      funcCall: "connectorsTunePolicyMenu()",
      header: toLocale("finStackExt::tunPolicies"),
      display: "dis",
      icon: "icon-document",
      iconType: "class",
      folderPathCount: 0,
      hideBackButton: true,
      action: "openMenu:null, null, 'policyInfo', {funcCall: 'connectorsPolicyInfo(@*~id*)', header: '*~dis*', display: 'dis', hasBadge: true, badgeType: 'normal', badgeValueFunc: 'priorityBadgeVal()', hideBackButton: true}",
      keepOpen: true,
      folderBadge: "tuning policies"
   }

  //add tuning policies button - takes user to new menu
  menuItems = menuItems.addAll([
    {
      displayName: toLocale("finStackExt::tunPolicies"),
      link: "",
      appId: "",
      icon: "icon-information",
      iconType: "class",
      hasBadge: true,
      ignoreSettings: marker(),
      badgeValue: numberPolicies,
      badgeType: "normal",
      badgeTooltip: numberPolicies +  " "+toLocale("finStackMobileExt::policies"),
      action: "window.app.ObtainMenu(null, null, 'tuningPolicies', " + settings.toAxonCode + ")",
      level: 0,
      order: -1012,
      ui: "html",
      //minUiTarget: "phone",
      keepOpen: true
    },

    {
      displayName: toLocale("finStackExt::coreRefresh"),
      appId: "refreshVars",
      ignoreSettings,
      action: "window.app.ObtainMenu(null, '{{targetRef}}','connectors', " + connectorsMenuSettings(viewAll).toAxonCode + ")",
      icon: "icon-retweet",
      iconType: "class",
      keepOpen:true,
      order: -1009
    },

    {
      displayName: if(targetRef == null or viewAll) toLocale("finStackMobileExt::allConn") else readById(targetRef).dis,
      isDivider: "true",
      order: -1011,
      ignoreSettings,
    }
  ])

  //add nack button that points to previous targetRef if viewAll
  if(viewAll)
    menuItems = menuItems.addAll(finStackMenuBackButton(toLocale("finStackExt::rightMenuConnectors"), connectorsMenuSettings(), "targetConns"))

  menuItems
end


def ​

func:connectorsMenuSettings ​

connectorsMenuSettings(viewAll: false) ​

Axon function


meta ​

deffunc:connectorsMenuSettings
isfunc
liblib:finStackMobile
nameconnectorsMenuSettings
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(viewAll:false) => do
  settings: {
    funcCall: if(viewAll) "connectorsMenu({{targetRef}}, true)" else "connectorsMenu({{targetRef}})",
    header: toLocale("finStackExt::rightMenuConnectors"),
    folderPath:"",
    action: "openMenu:null, null, 'selectedConnector', {funcCall: 'connectorSelectedMenu(@*~id*)', header: '*~dis*', hideBackButton: true}",
    folderPathCount:0,
    paginateCount: 100,
    keepOpen:true,
    icon: "icon-loading",
    iconType: "class",
    iconTooltip: "{uri}",
    rightIconFunc: "connectorsRightIcon()",
    rightIconType: "class",
    rightIconTooltip: "{connStatus}",
    folderBadge: "connectors",
    hideBackButton: true
  }

end


def ​

func:connectorsPointIcons ​

connectorsPointIcons(item) ​

Axon function


meta ​

deffunc:connectorsPointIcons
isfunc
liblib:finStackMobile
nameconnectorsPointIcons
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(item) => do
  if(item.has("sensor"))
    return "sm-sensor"
  else if(item.has("cmd"))
    return "sm-command"
  else if(item.has("sp"))
    return "sm-softpoint"
  else
    return "icon-location"
end


def ​

func:connectorsPolicyInfo ​

connectorsPolicyInfo(id) ​

Axon function


meta ​

deffunc:connectorsPolicyInfo
isfunc
liblib:finStackMobile
nameconnectorsPolicyInfo
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(id) => do
  curStats: finTuningPolicyGetStats([readById(id)], true)[0]
  menuList:[]

  curStats.each((v, k) => menuList = menuList.add({dis: k, val: v, action:"null", keepOpen: true}))

  menuList = menuList.addAll([
    {displayName: "— "+toLocale("finStackExt::rightMenuConnectors")+" —", isHeader: true, isDivider: true, ignoreSettings, order: -9999},
    {
      displayName: toLocale("finStackExt::coreEdit") + " " + readById(id).dis,
      link: "",
      appId: "editPolicy",
      icon: "icon-document-edit",
      iconType: "class",
      action: "finstack.eval('finFormCreateTuningPolicy(" + id.toAxonCode + ")')",
      level: 0,
      order: 1,
      ui: "html",
      keepOpen: true,
      ignoreSettings
    },
  ])

  backSettings: {
      funcCall: "connectorsTunePolicyMenu()",
      header: toLocale("finStackExt::tunPolicies"),
      display: "dis",
      icon: "icon-document",
      iconType: "class",
      folderPathCount: 0,
      hideBackButton: true,
      action: "openMenu:null, null, 'policyInfo', {funcCall: 'connectorsPolicyInfo(@*~id*)', header: '*~dis*', display: 'dis', hasBadge: true, badgeType: 'normal', badgeValueFunc: 'priorityBadgeVal()', hideBackButton: true}",
      keepOpen: true,
      folderBadge: "tuning policies"
   }
  menuList.addAll(finStackMenuBackButton(readById(id).dis, backSettings, "tuningPolicies"))
end


def ​

func:connectorsRightIcon ​

connectorsRightIcon(connector) ​

Axon function


meta ​

deffunc:connectorsRightIcon
isfunc
liblib:finStackMobile
nameconnectorsRightIcon
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(connector) => do
  status: null

  if(connector.has("connStatus"))
    status = connector->connStatus

  if(status == null or status == "unknown")
    return "icon-question"
  else if(status == "disabled")
    return "icon-cross"
  else if (status == "error" or status == "fault" or status == "down")
    return "icon-warning"
  else if (status == "ok")
    return "icon-checkmark"
end


def ​

func:connectorsShowPoints ​

connectorsShowPoints(id, path: null) ​

Axon function


meta ​

deffunc:connectorsShowPoints
isfunc
liblib:finStackMobile
nameconnectorsShowPoints
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(id, path:null) => do
  connType: readAllTagNames(id == id).find(v => v->name.endsWith("Conn"))->name
  results: [{dis: toLocale("finStackMobileExt::errGettingPointsMsg"), ignoreSettings, appId: "error", keepOpen:true,action: "null"}]

  debugInfo:{
    displayName: toLocale("finStackMobileExt::toolTipConnDebugInfo"),
    link: "",
      appId: "connectorDebug",
      icon: "icon-information",
      iconType: "class",
      action: "window.app.ObtainMenu(null, null, 'connectorDebug', {funcCall: 'connectorsDebugInfoMenu(" + id.toAxonCode + ")', header: 'Debug Info', paginateCount: 75, hideBackButton: true, keepOpen:true})",
      level: 0,
      order: -1001,
      ui: "html",
      keepOpen: true,
      ignoreSettings
  }

  results = eval("secureReadAll(point and " + connType + "Ref == " + id.toAxonCode + ")")

  if(results.size == 0)
    results = [{displayName: toLocale("finStackExt::noPtsFound"), ignoreSettings, appId: "none", action: "null", keepOpen:true}].toGrid

  results = results.addRow({displayName: "— "+toLocale("finStackExt::rightMenuConnectors")+" —", isHeader: true, isDivider: true, ignoreSettings, order: -9999})

  settings: {
    funcCall: "connectorSelectedMenu(" + id.toAxonCode + ")",
    hideBackButton: true
  }

  finStackMenuBackButton(readById(id).dis, settings, "selectedConnector").addAll(results.toRecList).add(debugInfo)
end


def ​

func:connectorsTunePolicyMenu ​

connectorsTunePolicyMenu() ​

Axon function


meta ​

deffunc:connectorsTunePolicyMenu
isfunc
liblib:finStackMobile
nameconnectorsTunePolicyMenu
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

() => do
  finStackMenuBackButton(toLocale("finStackExt::tunPolicies"), connectorsMenuSettings(), "connectors").addAll([
    {displayName: "— "+toLocale("finStackExt::rightMenuConnectors")+" —", isHeader: true, isDivider: true, ignoreSettings, order: -9999},
    {
      displayName: toLocale("finStackMobileExt::createNewPolicy"),
      link: "",
      appId: "newPolicy",
      icon: "icon-document-new",
      iconType: "class",
      action: "finstack.eval('finFormCreateTuningPolicy(0)')",
      level: 0,
      order: 1,
      ui: "html",
      keepOpen: true,
      ignoreSettings
    },

    {
      displayName: toLocale("finStackMobileExt::viewAllTuningStats"),
      link: "",
      appId: "policyStats",
      icon: "icon-document",
      iconType: "class",
      action: "finstack.eval('finTuningPolicyStatsForm(null,null)')",
      level: 0,
      ui: "html",
      order: 2,
      keepOpen: true,
      ignoreSettings
    },

    {
      displayName: "",
      link: "",
      isDivider: true,
      order: 3,
      ui: "html",
      ignoreSettings
    },
  ]).addAll(secureReadAll(connTuning).toRecList)
end


def ​

func:dbAddEditCommit ​

dbAddEditCommit(recId: null, props, folderPath: null, emptyFolderId: null) ​

Axon function


meta ​

deffunc:dbAddEditCommit
isfunc
liblib:finStackMobile
namedbAddEditCommit
overridable✓
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(recId: null, props, folderPath: null, emptyFolderId: null) => do
  password: null

  if (props.names.contains("secret"))
  do
    password = props->secret
    props = props.merge({-secret})
  end

  if(recId == null)
  do
    recId = diff(null, props.merge({folderPath: folderPath}), {add}).commit->id

    if(emptyFolderId != null) folderPathDelete(emptyFolderId)
  end
  else readById(recId).diff(props).commit

  //if(password != null and password != "******") passwordSet(recId, password)
  if(password != null and not password.replace("*", "").isEmpty) passwordSet(recId, password)
end


def ​

func:dbBuilderCreateLearnPointsJob ​

dbBuilderCreateLearnPointsJob(connRef, connType: "bacnet", learnPath: null) ​

Axon function


meta ​

deffunc:dbBuilderCreateLearnPointsJob
isfunc
liblib:finStackMobile
namedbBuilderCreateLearnPointsJob
overridable✓
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(connRef, connType: "bacnet", learnPath: null) => do
  // first, remove all expired discovered points regardless of connRefs
  finDbRemoveDiscoveredPoints()

  // get connector record and any non-expired discovered points
  connector: readById(connRef, false)
  existingPts: readCount(connRef == connector->id and connPointDiscovery and not fromTree)

  if (not funcs(name == connType+"Ping").isEmpty and (connector["status"] == null or (["down", "fault"]).contains(connector["status"])))
  do
    // ping the connector
    try eval(connType+"Ping("+connRef.toAxonCode+")")
    catch return finFormAlertOk(toLocale("finStackExt::regError"), toLocale("finStackMobileExt::connectorNotFound"))
  end

  // the connector was found
  if(connector != null)
  do
    jobToRun:{
      dis: toLocale("finStackMobileExt::discoverPointsFromConn").replace("{connDis}", connector.dis),
      job,
      jobExpr: "dbDiscoverConnPoints("+connRef.toAxonCode+", "+connType.toAxonCode+", {jobRec: jobCurRec(), learn: "+learnPath.toAxonCode+"})",
      percent: 1,
      connRef: connRef,
      pointDiscoveryJob
    }

    if (existingPts > 0)
      jobToRun = jobToRun.merge({usingPrevious})

    jobToRun = diff(null, jobToRun, {add}).commit

    eval("jobRun("+jobToRun->id.toAxonCode+")")

    return getConnPoints(connRef, jobToRun->id)
  end

  // connector not found
  else
    finFormAlertOk(toLocale("finStackExt::regError"), toLocale("finStackMobileExt::connectorNotFound"))
end


def ​

func:dbBuilderDiscoverBacnetPoints ​

dbBuilderDiscoverBacnetPoints(connRef, jobRec, folder: null) ​

Axon function


meta ​

deffunc:dbBuilderDiscoverBacnetPoints
isfunc
liblib:finStackMobile
namedbBuilderDiscoverBacnetPoints
overridable✓
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(connRef, jobRec, folder: null) => do
  connectorPts: [].toGrid
  learnedPts: readAll(point and bacnetConnRef == connRef)
  folders: bacnetLearn(connRef).colToList("learn")

  folders.each((x, i) => do
    newPercent: finPrecision(((i + 1) / folders.size) * 100, 0)
    pointsFound: bacnetLearn(connRef, x)
    colName: pointsFound.colNames.findAll(v => not (["is"]).contains(v))

    bacnetLearn(connRef, x).toRecList.each(r => do
      markerList: "{"

      colName.each col => do
        if(not r.has(col) or r[col] == null) markerList = markerList + "-"+col+","
      end

      if(markerList != "{") r = r.merge(eval(markerList[0..-2] + "}"))
      if(learnedPts.find(v => r.has("bacnetCur") and v->bacnetCur == r->bacnetCur) != null)
        diff(null, r.merge({is: x.toStr, disabledInGrid, connPointDiscovery, connRef: connRef, tempId: "connLearn:"+connRef+":"+x+":"+(if(r.has("bacnetCur")) r->bacnetCur else if(r.has("bacnetHis")) r->bacnetHis else "null")}), {add}).commit
      else
        diff(null, r.merge({
          connPointDiscovery,
          connRef: connRef,
          is: x.toStr,
          tempId: "connLearn:"+connRef+":"+x+":"+(if(r.has("bacnetCur")) r->bacnetCur else if(r.has("bacnetHis")) r->bacnetHis else "null")
        }), {add}).commit
    end)

    jobRec.diff({percent: newPercent}, {force}).commit
  end)
end


def ​

func:dbBuilderDiscoverConnectors ​

dbBuilderDiscoverConnectors(discoverId: null, connType: "bacnet", useConnDiscover: false) ​

Axon function


meta ​

deffunc:dbBuilderDiscoverConnectors
isfunc
liblib:finStackMobile
namedbBuilderDiscoverConnectors
overridable✓
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(discoverId:null, connType: "bacnet", useConnDiscover: false) => do //waitForNames: true
  discoverRec: null
  recsToMark: []

  if (connType.endsWith("Conn"))
    connType = connType[0..-5]

  /*
   * if this is a new discovery
   * read saved discovery settings or use default
   * begin the discovery
   * return any results along with meta data for re-query
  */
  if(discoverId == null)
  do
    // can use the discovery method below finBeginDiscovery
    // requires a fin{connType}DeviceDiscovery function
    if (not useConnDiscover)
    do
      discoverSettings: if (connType == "bacnet") read(bacnetDiscoverSettings, false) else null

      if(discoverSettings == null)
        discoverSettings = try finGetDiscoveryConfiguration(connType).gridRowsToDict((row, index) => row->name, (row, index) => row->defaultValue).ioWriteZinc("") catch null
      else do
        if(read(ext == "bacnetMstp", false) == null) discoverSettings = discoverSettings.merge({-baudRate, -serialPort, -id, -bacnetDiscoverSettings, -mod}).ioWriteZinc("")
        else discoverSettings = discoverSettings.merge({-id, -bacnetDiscoverSettings, -mod}).ioWriteZinc("")
      end

      //begin new discovery and add tags relevent to reporting percentage
      discoverRec = finBeginDiscovery(connType, discoverSettings)[0].diff({startTime: now(), timeout: try discoverSettings.ioReadZinc()[0]->discoveryTimeout catch 8000, percent: 0}).commit

      //grab new results that have the name added and mark them
      recsToMark = finDiscoveryStatusCheck(discoverRec["id"]).findAll(v => not v.has("addedToDb") and not v.dis.startsWith("DEV"))
    end

    // use conn discover
    else
    do
      discoverDict: {
        extName: connType,
        extRef: try read(ext == connType)->id catch null,
        finDiscovery,
        dis: connType + " DB Discovery Session",
        startTime: now(),
        timeout: 8000,
        percent: 0,
        status: "running"
      }

      discoverRec = diff(null, discoverDict, {add}).commit

      // evaling since jobRun doesnt seem to include variable values
      eval("jobRun(finDbConnDiscover("+discoverRec["id"].toAxonCode+","+connType.toAxonCode+"))")
    end

    if(not recsToMark.isEmpty)
    do
      recsToMark.each x => x.diff({"addedToDb"}).commit
      recsToMark = recsToMark.colToList("id")
    end
    else if (recsToMark.isGrid)
      recsToMark = recsToMark.toRecList

    return finDbMakeConnectorGrid("readByIds("+recsToMark.toAxonCode+")" + //dbConnectorsGrid
                            ".map(r => if(readAll("+connType+"Conn).find(v => v.has(\"uri\") and (v->uri == r->uri)) != null) r.merge({disabledInGrid}) else r)"+
                            ".addMeta({idToWatch: "+discoverRec["id"].toAxonCode+", percent: "+discoverRec->percent+", query: \"dbBuilderDiscoverConnectors("+discoverRec["id"].toAxonCode+", \\\""+connType+"\\\")\"})","discoverResults")
  end

  //if this is a query of a discovery
  else do
    discoverRec = readById(discoverId, false)

    if((discoverRec != null and discoverRec->status != "running") or (discoverRec->status == "running" and (now() - discoverRec->startTime > discoverRec->timeout) and finDiscoveryStatusCheck(discoverRec["id"]).size == 0)) do
      waitForNames: (now() - discoverRec->startTime >= (1.5 * discoverRec->timeout))

      if(waitForNames) do
        recsToMark = finDiscoveryStatusCheck(discoverRec["id"]).findAll(v => not v.has("addedToDb") and not v.dis.startsWith("DEV"))
      end else
        recsToMark = finDiscoveryStatusCheck(discoverRec["id"]).findAll(v => not v.has("addedToDb"))

      recsToMark.each x => x.diff({"addedToDb"}).commit

      if(recsToMark.has("id")) recsToMark = recsToMark.colToList("id")
      else recsToMark = recsToMark.toRecList

      finDiscoverySessionEnd(discoverRec["id"])

      return finDbMakeConnectorGrid("readByIds("+recsToMark.toAxonCode+").map(r => if(readAll("+connType+"Conn).find(v => v.has(\"uri\") and (v.dis + v->uri + v[\"path\"] == r.dis + r->uri + r[\"path\"])) != null) r.merge({disabledInGrid}) else r).addMeta({idToWatch: "+discoverRec["id"].toAxonCode+", percent: "+(if(waitForNames) 99 else 100)+", query: \"dbBuilderDiscoverConnectors("+discoverRec["id"].toAxonCode+ ", \\\""+connType+"\\\")\"})","discoverResults")
    end else do
      recsToMark = finDiscoveryStatusCheck(discoverRec["id"]).findAll(v => not v.has("addedToDb") and not v.dis.startsWith("DEV"))

      if(not recsToMark.isEmpty)
      do
        recsToMark.each x => x.diff({"addedToDb"}).commit
        recsToMark = recsToMark.colToList("id")
      end
      else
        recsToMark = []

      newPercent: now() - discoverRec->startTime
      newPercent = if(newPercent >= discoverRec->timeout) 99 else finPrecision(((newPercent.finRemoveUnits * 3600) / discoverRec->timeout) * 100, 0)

      //change so that dis is not relied upon to mark rows 'disabledInGrid'
      return finDbMakeConnectorGrid("readByIds("+recsToMark.toAxonCode+").map(r => if(readAll("+connType+"Conn).find(v => v.has(\"uri\") and v.has(\"path\") and (v.dis + v->uri + v->path == r.dis + r->uri + r->path)) != null) r.merge({disabledInGrid}) else r).addMeta({idToWatch: "+discoverRec["id"].toAxonCode+", percent: "+newPercent+", query: \"dbBuilderDiscoverConnectors("+discoverRec["id"].toAxonCode+", \\\""+connType+"\\\")\"})","discoverResults")
    end
  end //end of "if query"
end //end func


def ​

func:dbBuilderDropAction ​

dbBuilderDropAction(dragTargets, dropTarget, treeType: "") ​

Axon function


meta ​

deffunc:dbBuilderDropAction
isfunc
liblib:finStackMobile
namedbBuilderDropAction
overridable✓
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(dragTargets, dropTarget, treeType: "") => do
  dragTargets = try finFindNonDbRec(dragTargets) catch null
  dropTarget = readById(dropTarget, false)

  msg:[]
  action:""

  // if dragTargets are tag bundles:
  if(dragTargets.find(v => v.has("tagBundle")) != null)
  do
    // gather tagBundles
    dragTargets = dragTargets.findAll(v => v.has("tagBundle"))

    // if a saved filter, read query the filterString for ids
    // otherwise, just pass the ids
    if(dropTarget.has("filterString")) action = dropTarget->filterString.toAxonCode+".parseFilter.readAll.colToList(\"id\"))"
    else action = "["+dropTarget->id.toAxonCode+"])"

    action = "finApplyTagBundle("+dragTargets.toAxonCode+", "+action

    // if there are multiple tag bundles
    if(dragTargets.size > 1)
    do
      msg = [toLocale("finStackMobileExt::tagBundlesWillNotApplyTo").replace("{target}", dropTarget.dis)]
      tbList: []

      dragTargets.each x => tbList = tbList.add(x.dis)

      msg = msg.add({nameList: tbList, changing})
    end

    // single tag bundle
    else if(dragTargets.size == 1)
      msg = toLocale("finStackMobileExt::tagBundleWillBeAppliedTo").replace("{target}", dropTarget.dis).replace("{tagBundleName}", dragTargets[0].dis)

    // confirm with user
    finFormConfirmChangesAlert(action, msg)
  end

  // all others
  else do
    /*
      TODO:
      Better, more descriptive alert pop-up message.
    */
    finFormAlertOk(toLocale("finStackExt::warning"), toLocale("finStackMobileExt::invalidDropGeneric"))
  end
end


def ​

func:dbBuilderSelectAction ​

dbBuilderSelectAction(panelOpts, selectedRef: null) ​

Axon function


meta ​

deffunc:dbBuilderSelectAction
isfunc
liblib:finStackMobile
namedbBuilderSelectAction
overridable✓
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(panelOpts, selectedRef: null) => do
  query: panelOpts->baseQuery
  title: panelOpts->dis

  if(selectedRef != null and selectedRef.isRef) do
    title = title + " - " + readById(selectedRef).dis
    if(panelOpts.has("itemProperty")) query = readById(selectedRef)[panelOpts->itemProperty]
    else if(panelOpts.has("findRefs")) query = panelOpts->findRefs+" == "+selectedRef.toAxonCode
    else query = "id == "+selectedRef.toAxonCode
  end else if(selectedRef != null and selectedRef.isStr) do
    title = toLocale("finStackMobileExt::itemInObj").replace("{itemName}", title).replace("{objectName}", selectedRef.split("/")[-1])
    query = "readAll("+query+").findAll(v => v.has(\"folderPath\") and v->folderPath.toTagName.startsWith("+selectedRef.toTagName.toAxonCode+"))"
  end

  panel: {
    view: "default",
    panelTitle: title,
    viewId: panelOpts->dis.toTagName+"MainPanel",
    dis: panelOpts->dis,
    default: true,
    resolveWith: {type: "axon", action: "dbMakeDataGridPanel("+query.toAxonCode+", "+panelOpts->dis.toTagName.toAxonCode+")"}
  }

  if(panelOpts.has("panelTitle") and not selectedRef.isStr) panel = panel.set("panelTitle", panelOpts->panelTitle)

  return { panels: [panel] }
end


def ​

func:dbDiscoveryAdd ​

dbDiscoveryAdd(connectors, makeTemplate: false, refreshStr: "") ​

Axon function


meta ​

deffunc:dbDiscoveryAdd
isfunc
liblib:finStackMobile
namedbDiscoveryAdd
overridable✓
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(connectors, makeTemplate: false, refreshStr: "") => do
  names: ""
  connNames: connectors.readByIds.colToList("dis")
  errMsg: ""

  if(connNames.size > 1) do
    connNames.each x => do
      if(x == connNames[-1]) names = names + ", and " + x
      else if(x == connNames[0]) names = names + x
      else names = names + ", " + x
    end

    if(makeTemplate) do
      names = toLocale("finStackMobileExt::templatesCreatedFromConn").replace("{connName}", names)
      errMsg = toLocale("finStackMobileExt::templatesNotCreatedFromConn").replace("{connName}", names)
    end
    else do
      names = toLocale("finStackMobileExt::connsAdded").replace("{connList}", names)
      errMsg = toLocale("finStackMobileExt::connsNotAdded").replace("{connList}", names)
    end
  end
  else if (makeTemplate) do
    names = toLocale("finStackMobileExt::templateCreatedFromConn").replace("{connName}", connNames[0])
    errMsg = toLocale("finStackMobileExt::templateNotCreatedFromConn").replace("{connName}", connNames[0])
  end
  else do
    names = toLocale("finStackMobileExt::connAdded").replace("{connName}", connNames[0])
    errMsg = toLocale("finStackMobileExt::connNotAdded").replace("{connName}", connNames[0])
  end

  if(makeTemplate == false) do
    try do
      finDiscoveryAdd(connectors)
      finStackMenuOkForm(toLocale("finStackExt::bLineSuccess"), names, {completeAction: refreshStr})
    end catch
      finStackMenuOkForm(toLocale("finStackExt::regError"), errMsg)
  end else do
    try do
      finBacnetTemplateDiscoveryAdd(connectors)
      finStackMenuOkForm(toLocale("finStackExt::bLineSuccess"), names)
    end catch (error) do
      if (error.dis.contains("Invalid database tag")) finStackMenuOkForm(toLocale("finStackExt::regError"), error.dis.replace(reFind(r"\[.+\]", error.dis), ""))
      else finStackMenuOkForm(toLocale("finStackExt::regError"), errMsg)
    end
  end
end


def ​

func:dbDragActionAddConnector ​

dbDragActionAddConnector(dropTarget, dragItems, targetRef: null) ​

Axon function


meta ​

deffunc:dbDragActionAddConnector
isfunc
liblib:finStackMobile
namedbDragActionAddConnector
overridable✓
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(dropTarget, dragItems, targetRef: null) => do
//dbDragActionConnectors
  if(targetRef != null) do
    //dropTarget = finFindNonDbRec([dropTarget->id])
    //if(not dropTarget.has("connRef"))
    if(dropTarget == "connectorMainPanel")
      dropActionEquipTree(dragItems, targetRef)
    else
      finFormAlertOk(toLocale("finStackExt::regError"), toLocale("finStackMobileExt::howToAddConnPoints"))
  end else do
    //if(not dropTarget.has("connTagName"))
    if(dropTarget == "bacnetLearnedPanel")
      dbDiscoveryAdd(dragItems.map(r => r.replace("@", "").parseRef), false, "window.app.RefreshBuilderTreeNodeForId('@folderPath:bacnetConn:'); window.app.RefreshBuilderGridAt(0, 'panel')")
    else
      finFormAlertOk(toLocale("finStackExt::regError"), toLocale("finStackMobileExt::howToAddConnDevices"))
  end
end


def ​

func:dbGraphicPanels ​

dbGraphicPanels(nodeId, treeType: "") ​

Function returns a list of graphics whose graphicOns evaluate to nodeId. Each graphic will be in the panel-format used by the DB Builder's work area.

nodeId - The ID of the record to be used to find which graphics to return.

treeType - TODO


meta ​

constructdbGraphicPanels(read(site)->id, "equip")
deffunc:dbGraphicPanels
isfunc
liblib:finStackMobile
namedbGraphicPanels
overridable✓
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(nodeId, treeType: "") => do
  //for reference
  basicPanel: {
    view: "default",
    viewId: "basicPanel",
    dis: toLocale("finStackMobileExt::basicPanel"),
    default: false,
    finNetworkIgnore,
  }

  panelList: []
  graphicList: finGraphicOn(nodeId)

  if(not graphicList.isEmpty) do
    panelList = panelList.addAll(graphicList.toRecList.map ((x, i) => do
      basicPanel.merge({
        view: "iframe",
        viewId: "equipGraphic"+i,
        dis: x.dis,
        icon: "ic|icon-photo",
        url: if (not x.has("finExternalProject")) "/fin5/" + context()->projName + "?projectRef=" + x->id.toAxonCode + "&title=showSettings#targetRef="+nodeId.toAxonCode
              else x["uri"]
      })
    end))
  end

  return panelList
end


def ​

func:dbMakeDataGridPanel ​

dbMakeDataGridPanel(panelFilter, type: "equip", folderPath: "", navNameForDis: true, hiddenCols: []) ​

Constructs a basic grid panel to be used with the DB Builder app. This panel will always be marked as the default panel.

Returns a dict with the properties columns and data.

panelFilter - A string filter to retrieve data to be displayed in the grid panel.

type - Default value is "equip". A string containing the type of tree the grid is being created for. Only "equip" and "schedule" are supported at this time

  • equip: grid displays flat list of items found with panelFilter.
  • schedule: grid displays all matching schedules and has the option to expand a schedule in the grid to show all items with it as a scheduleRef.

meta ​

constructdbMakeDataGridPanel("siteRef == " +read(site)->id+" and ...
deffunc:dbMakeDataGridPanel
isfunc
liblib:finStackMobile
namedbMakeDataGridPanel
overridable✓
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(panelFilter, type: "equip", folderPath: "", navNameForDis: true, hiddenCols:[]) => do
  if(folderPath == null) folderPath = ""
  cols:[]
  iconList: ["icon-info"]
  navList: read(navMeta)->equipPath.split("/").map(r => reFind(r"[a-zA-Z_0-9]+", r))
  curValFormat: ""
  colNameKey: {
    ip: toLocale("finStackMobileExt::ipAddress"),
    deviceInstance: toLocale("finStackMobileExt::deviceInstance"),
    macAddress: toLocale("finStackMobileExt::macAddress"),
    networkNumber: toLocale("finStackMobileExt::networkNumber")
  }

  colBlackList: [
    "icon", "disMacro", "actions", "mod", "tz", "schedule", "childNodes", "exploreAction", "folderPath", "iconTable", "icon24",
    "id", "essentialsIcon", "essentials", "connProto", "finDiscoveryRef", "connTagName", "file", "isBranch", "finThumb", "finScreenshot"
  ]

  hiddenCols = hiddenCols.add("fakeId")

  if(type == "discoverResults" or (type=="connectors" and panelFilter == "bacnetConn"))
    colBlackList = colBlackList.addAll(["scheduleRef", "connState", "bacnetVersion", "bacnetDeviceName", "bacnetDeviceStatus"])

  //format data
  data: try readAll(parseFilter(panelFilter))
        catch do
          try eval(panelFilter).toGrid
          catch [].toGrid
        end

  data = data.finGridFilter(not emptyFolder)

  if(folderPath != "") do
    data = data.findAll(v => v.has("folderPath") and (v->folderPath.startsWith(folderPath + "/") or ("/"+v->folderPath).startsWith(folderPath + "/") or v->folderPath == folderPath or "/"+v->folderPath == folderPath))
  end

  data = data.map(r => do
    if (r.has("id") and not r->id.toStr.startsWith("p") and readById(r->id, false) == null)
    do
      r = r.merge({-id, fakeId: r->id})
    end

    if(r.has("curVal") and r->kind == "Number") do
      if(r.has("precision")) do
        num: finPrecision(r->curVal, r->precision)

        if(r.has("unit")) r = r.set("curVal", parseNumber(num + r->unit))
        else r = r.set("curVal", num)
      end
    end

    else if(r.has("curVal") and r->kind == "Bool")
    do
      r = r.set("curVal", r->curVal.toStr)
    end

    r.names.each x => if(r[x].isRef and x != "id" and readById(r[x], false) != null) r = r.set(x, readById(r[x]).dis)

    if(not r.has("icon")) do
      if(type == "tagBundle") r = r.set("icon", "ic|icon-tags")
      else if(panelFilter == "fin5" or panelFilter.startsWith("readAll(fin5")) r = r.set("icon", "ic|icon-photo")
      else if(r.has("site")) r = r.set("icon", "ic|sm-site")
      else if(r.has("floor")) r = r.set("icon", "ic|sm-floors")
      else if(r.has("equip")) r = r.set("icon", "ic|sm-equip")
      else if(r.has("point")) r = r.set("icon", "ic|sm-point")
    end

    if((type == "schedule" and (panelFilter == "schedule" or panelFilter.startsWith("readAll")) and readAll(scheduleRef == r->id).size > 0)
      or (type == "graphics" and (panelFilter == "fin5" or panelFilter.startsWith("readAll")))) do
      childData: try if(type == "schedule") readAll(scheduleRef == r->id) else readAll(r->graphicOn.parseFilter) catch []

      if(not childData.isEmpty())
        childData = childData.map(x=> x.set("dis", x.dis)).sort("dis")

      r = r.merge({
        isBranch: true,
        childNodes: childData.map(item => do
          navStr: item.finNavMetaWhoAmI()
          descStr: if(navStr == "equip" and item.has("equipRef")) "equipRef" else if(navStr != null) navList[navList.index(navStr) - 1] + "Ref" else if(item.has("topLevel")) toLocale("finStackMobileExt::topLevelDis") else "Ref"
          navPos: navList.index(navStr)

          if(navPos == null) navPos = navList.size
          if(navStr == "floor") navStr = navStr+"s"

          if(descStr == "floorRef") descStr = item[descStr].readById->siteRef.readById.dis + " " + item[descStr].readById.dis
          else if(descStr != "Ref" and descStr != "nullRef" and descStr != toLocale("finStackMobileExt::topLevelDis")) descStr = item[descStr].readById.dis
          else if(descStr != toLocale("finStackMobileExt::topLevelDis")) descStr = item.dis

          item.merge({
            label: if(descStr == toLocale("finStackMobileExt::topLevelDis")) descStr else if(item["navName"] != null) item->navName else item.dis,
            icon: "sm-"+navStr,
            description: if(item["navName"] != null) descStr else null,
            navTag: navPos
          })
        end).sort((a, b) => (a->navTag + a->label) <=> (b->navTag + b->label))
      })

    end else if(type == "connectors" or type == "discoverResults") do
      if(not panelFilter.startsWith("bacnetConnRef"))
        r = r.merge({
          ip: try uriVal.split("/")[0] catch "",
          deviceInstance: try uriVal.split("/")[1].split("?")[0] catch "",
          networkNumber: try reFind(r"dnet=\d+", uriVal.split("/")[1].split("?")[1]).replace("dnet=", "") catch "",
          macAddress: try reFind(r"dadr=[abcdef\d]+", uriVal.split("/")[1].split("?")[1]).replace("dadr=", "") catch ""
        })

      if(panelFilter == "finConnExts()" and readAll(parseFilter(r->tag)).size > 0) do
        r = r.merge({
          isBranch: true,
          childNodes: readAll(parseFilter(r->tag)).map(item => {label: item.dis, description: item->uri.toStr, icon: "icon-network-3"})
        })
      end else if(panelFilter == "bacnetConn") do
        uriVal: r->uri.toStr.replace("bacnet://", "")

        r = r.merge({
          -bacnetDeviceName,
          connStatus: try r->connStatus catch "",
          connError: try r->connErr catch "",
          ip: try uriVal.split("/")[0] catch "",
          deviceInstance: try uriVal.split("/")[1].split("?")[0] catch "",
          networkNumber: try reFind(r"dnet=\d+", uriVal.split("/")[1].split("?")[1]).replace("dnet=", "") catch "",
          macAddress: try reFind(r"dadr=[abcdef\d]+", uriVal.split("/")[1].split("?")[1]).replace("dadr=", "") catch ""
        })
      end
    end

    if(navNameForDis and r.has("navName")) r.merge({dis: r->navName})
    else if(r.dis != "") r.merge({dis: r.dis})
    else r
  end)

  if(data.has("dis")) data = data.sort("dis")
  colOrder: data.colNames.findAll(v => v != "dis").sort()

  each(data.gridColKinds) (x, i) => do
    colType: x->kind.split("|")[0]

    colProps: {
      property: x->name,
      displayName: if(colNameKey.has(x->name) and (type == "discoverResults" or type == "connectors")) colNameKey[x->name] else x->name,
      type: if(colType == "Ref") "Str" else colType,
      columnType: "default",
      button: false,
      enabled: if((x->kind == "Marker" and x->name != "disabled") or x->kind == "Ref" or colBlackList.contains(x->name) or hiddenCols.contains(x->name)) false else true,
      iconField: if(x->name == "dis" and data.has("icon")) "icon" else null,
      order: if(x->name == "dis") 0 else eachWhile(colOrder) (col, index) => if(col == x->name) (index + 1),
      format: if((x->kind == "Number" or x->kind.contains("Number")) and (["maxVal", "curVal", "minVal", "writeVal"]).contains(x->name)) "0,0.[000000000000]" else if(x->kind == "Number") "0" else null
    }
    if(not colBlackList.contains(x->name))
      cols = cols.add(colProps)
  end

  data.toGrid.addMeta({columns: cols.toGrid.sort("order").toRecList})
end


def ​

func:dropActionConnectorTree ​

dropActionConnectorTree(dragTargets, dropTarget) ​

Axon function


meta ​

deffunc:dropActionConnectorTree
isfunc
liblib:finStackMobile
namedropActionConnectorTree
overridable✓
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(dragTargets, dropTarget) => do
  dragTargets = dragTargets.map(r => if(r.isStr) r.replace("@", "").parseRef else r)
  //get actual records
  dragTargets = try finFindNonDbRec(dragTargets) catch null //dragTargets.map(r => r.replace("@", "").parseRef.readById(false))
  dropTarget = readById(dropTarget, false)

  connTag: dropTarget.names.find(v => v.contains("Conn"))
  connRefType: connTag.replace("Conn", "") //finConnectorTypes().find(v => connTag.contains(v->name))->name

  action: ""
  msg: []
  tbMsg: toLocale("finStackMobileExt::multipleTagBundlesApplied").replace("{item}", dropTarget.dis)
  tbList: []
  eqList: []
  tpList: []
  tpMsg: ""
  tpApplied: false
  eqMsg: toLocale("finStackMobileExt::connectorWillReplaceConnRefsOnPoints").replace("{connDis}", dropTarget.dis).replace("{connType}", connRefType)
  scheduleApplied: false
  schedList: []
  schedMsg: ""
  connRefType = connRefType + "ConnRef"

  if(dragTargets == null) do
    msg = toLocale("finStackMobileExt::incorrectItemsForEquipTreeErr")
    dragTargets = []
  end

  dragTargets.each(item => do
    itemNav: finNavMetaWhoAmI(item)
    newProps: {}

    if(itemNav != null and not item.has("schedule")) do
      uniqueConns: null

      newProps = newProps.set(connRefType, dropTarget->id)

      if(itemNav == "point" and item.has(connRefType)) do
        action = "{id:"+item->id.toAxonCode+", newProps:"+newProps.toAxonCode+"}" //"readById("+item->id.toAxonCode+").diff("+newProps.toAxonCode+").commit"
        eqList = eqList.add(item.dis)
      end else
        readAll(parseFilter(itemNav+"Ref == "+item->id.toAxonCode+" and "+connRefType)).each pt => do
          action = "{id:"+pt->id.toAxonCode+", newProps:"+newProps.toAxonCode+"}"
          eqList = eqList.add(item.dis)
        end
    end

    //schedules
    else if(item.has("schedule") and not scheduleApplied) do
      newProps = {scheduleRef: item->id}
      schedList = schedList.add(item.dis)
      action = action + "{id:"+dropTarget->id.toAxonCode+", newProps: "+newProps.toAxonCode + "}, "
      scheduleApplied = true

      if(dropTarget.has("scheduleRef"))
        schedMsg = toLocale("finStackMobileExt::scheduleWillReplaceAssigned").replace("{curScheduleDis}", readById(dropTarget->scheduleRef).dis).replace("{scheduleDis}", item.dis)
      else
        schedMsg = toLocale("finStackMobileExt::scheduleWillApplyToTarget").replace("{scheduleDis}", item.dis).replace("{targetDis}", dropTarget.dis)
    end

    //tagBundles
    else if(item.has("tagBundle")) do
      action = item.toAxonCode + ","

      tbList = tbList.add(item->dis)
    end

    //tuning policy
    else if (item.has("connTuning") and not tpApplied)
    do
      newProps = {connTuningRef: item->id}
      tpList = tpList.add(item.dis)
      tpApplied = true

      action = action + "{id:"+dropTarget->id.toAxonCode+", newProps: "+newProps.toAxonCode + "}, " //"readById("+dropTarget->id.toAxonCode+").diff("+newProps.toAxonCode+").commit"

      if(dropTarget.has("connTuningRef"))
        tpMsg = toLocale("finStackMobileExt::tuningPolicyWillReplaceAssigned").replace("{curPolicy}", readById(dropTarget->connTuningRef).dis).replace("{policyDis}", item.dis)
      else
        tpMsg = toLocale("finStackMobileExt::tuningPolicyWillApplyToTarget").replace("{policyDis}", item.dis).replace("{targetDis}", dropTarget.dis)
    end
  end)

  if(not action.isEmpty()) action = "["+action[0..-2] + "].each x => if(not x.has(\"tagBundle\")) readById(x->id).diff(x->newProps).commit() else finApplyTagBundle(x, ["+dropTarget->id.toAxonCode+"])"

  if(tbList.isEmpty and schedList.isEmpty and eqList.isEmpty and tpList.isEmpty) finFormAlertOk(toLocale("finStackExt::regError"), toLocale("finStackMobileExt::incorrectItemsForEquipTreeErr"))
  else do
    if(not schedList.isEmpty) msg = schedMsg //msg.add(schedMsg).add({nameList: schedList, changing})
    if(not tbList.isEmpty) msg = msg.add(tbMsg).add({nameList: tbList, changing})
    if(not eqList.isEmpty) msg = msg.add(eqMsg).add({nameList: eqList, changing})
    if(not tpList.isEmpty) msg = tpMsg //msg.add(tpMsg).add({nameList: tpList, changing})

    finFormConfirmChangesAlert(action, msg)
  end
end


def ​

func:dropActionEquipTree ​

dropActionEquipTree(dragTargets, dropTarget, haystackConnRef: null) ​

Determines and takes the appropriate action for when an item is dropped onto an item within the equip tree in the DB Builder app.

Supports the following items dropped onto the equip tree:

  • connectors: If the item is a point and the connTypes match , replace it's existing connRef with the new one. If the item is anything else, replace all of it's childrens connRefs with the new one.
  • schedules: Replaces and item's scheduleRef.
  • equip tree items: Moves the dropped items to the new location. (Drag an equip to a different floor and the equip's floorRef will be updated.

dragTargets - A list of ids as strings. (The items dropped)

dropTarget - The id of the target for the drop action. (The target of the dragTargets)


meta ​

constructdropActionEquipTree([read(equip)->id.toAxonCode], read(f...
deffunc:dropActionEquipTree
isfunc
liblib:finStackMobile
namedropActionEquipTree
overridable✓
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(dragTargets, dropTarget, haystackConnRef: null) => do
  path: null
  curTime: now()
  runAsJob: false
  userIsOp: finGetCurrentUser()->userRole == "op"

  if(dragTargets.isDict and dragTargets.has("ids"))
  do // assumed items from a connector are being dropped onto equip tree
    if (dragTargets->ids[0].startsWith("@modbus:"))
    do // modbus specific
      dragTargets = dragTargets->ids.map(r => {connRef: r.split(":")[1..-2].concat(":").parseRef, name: r.split(":")[-1], modbus})
    end
    else if(dragTargets->ids[0].startsWith("@conn-"))
    do
      //@connPt:p:demo:r:123123-123:knxAddr:1-2-4:45
      dragTargets = dragTargets->ids.map(r => {connRef: r.split(":")[1..4].concat(":").parseRef, addrPathReplaceVal: r.split(":")[-1], addrPath: r.split(":")[6], addrPathName: r.split(":")[5], connType: r.split(":")[0].replace("@conn-","")})
    end
    else if(haystackConnRef == null or haystackConnRef == "undefined")
    do // all other conns
      dragTargets = dragTargets->ids.findAll(v=> v != null and not v.isEmpty()).map(x => x.replace("@", "").parseRef)
    end
    else
    do // assume haystack specific
      ids: dragTargets->ids
      hsCurs: dragTargets->hsCurs
      hsPrev: dragTargets->hsPrev
      learns: dragTargets->learns

      tempList: []

      ids.each((x,i) =>
      do
        if (hsCurs[i] == null or not hsCurs[i].startsWith("@"))
        do // not points?
          if (hsPrev[i] == null and learns[i] == null)
            tempList = tempList.add(x)
          else
            tempList = tempList.add({id: x, haystackCur: hsCurs[i], previousLearn: hsPrev[i], learn: learns[i]})
        end
        else // haystack points?
          tempList = tempList.add({haystackCur: hsCurs[i]})
      end)

      dragTargets = tempList
    end
  end
  else if (dragTargets.isRef and haystackConnRef != null and haystackConnRef.isStr and haystackConnRef == "addAll")
  do
    connectorRecord: readById(dragTargets, false)
    dragTargets = readAll(connPointDiscovery and connRef == dragTargets and not disabledInGrid)

    if (connectorRecord.has("bacnetConn") and connectorRecord.has("discoveryFilters")) do
      discoveryFilters: connectorRecord["discoveryFilters"]

      dragTargets = dragTargets.findAll(point => do
        pointPath: null

        if (point["bacnetCur"] != null)
          pointPath = point["bacnetCur"]
        else if (point["bacnetWrite"] != null)
          pointPath = point["bacnetWrite"]
        else
          pointPath = point["bacnetHis"]

        if (pointPath != null) do
          pathPrefix: reFind(r"\D+", pointPath)
          instanceNumber: pointPath.replace(pathPrefix, "").parseNumber
          return discoveryFilters.any(filter => do
            return (pathPrefix == filter["pointType"] and filter["instanceMinRange"] <= instanceNumber and filter["instanceMaxRange"] >= instanceNumber)
          end)
        end
        return true // FT-2861 including bacnet discovered directories
      end)
    end

    if (not dragTargets.isEmpty())
      dragTargets = dragTargets.colToList("id")

    runAsJob = true
  end

  // get actual records

  if(runAsJob or haystackConnRef == null or haystackConnRef == "undefined")
  do // not haystack
    if(not dragTargets[0].isDict()) dragTargets = try finFindNonDbRec(dragTargets) catch null
    else if(not dragTargets[0].has("modbus")) dragTargets = finGenerateConnPoints(dragTargets)
    else dragTargets = finGenerateModbusPoints(dragTargets)

    haystackConnRef = null
  end
  else
  do // assume haystack
    if(haystackConnRef.isStr and not haystackConnRef.startsWith("@")) do
      haystackConnRef = read(parseFilter("haystackConn and dis == "+haystackConnRef.toAxonCode), false)

      if(haystackConnRef != null) haystackConnRef = haystackConnRef->id
      else dragTargets = null
    end else if(haystackConnRef.isStr) do
      haystackConnRef = haystackConnRef[1..-1].parseRef(false)

      if(haystackConnRef == null) dragTargets = null
    end

    if(dragTargets != null)
    do
      dragTargets = dragTargets.map(row =>
      do
        if(row.isStr and row.startsWith("@p")) // re-set row to be record from db
          row = readById(row[1..-1].parseRef)

        thisHaystackCur: if(row.isDict and row.has("haystackCur")) row->haystackCur else if(row.isDict and row.has("id")) row->id else row
        path = (if(thisHaystackCur.startsWith("C.")) "slot:"+thisHaystackCur[1..-1] else if(thisHaystackCur.startsWith("S.")) "sep:"+thisHaystackCur[1..-1] else thisHaystackCur.replace("@C", "slot:").replace("@S", "sep:").replace("@", "")).split(".")

        if((path[0].startsWith("sep") or path[0].startsWith("slot")) and not (row.isDict and row.has("previousLearn")))
          path = if(path.size > 2) path[0..-2].concat("/") else path[0] + "/"
        else
        do
          if(row.isDict and row.has("previousLearn")) // set path to previousLearn
            path = if (row->previousLearn.startsWith("nav:")) row->previousLearn.parseRef else row->previousLearn
          else if(not row.isDict) // old learn paths from haystack connections
            path = "equip:/"+thisHaystackCur.replace("@", "")
          else // set path to root call
            path = null
        end

        // query the connector using the learn/nav path assigned above
        results: finHaystackLearn(haystackConnRef, path)

        if(results.has("point"))
          results = results.find(v => (v.has("haystackCur") and v->haystackCur.toStr.replace("@", "") == thisHaystackCur.toStr.replace("@", "")) or (not v.has("haystackCur") and row.isDict and row.has("id") and v->id.toStr == row->id.toStr.replace("@", ""))) //.merge({connRef: haystackConnRef})
        else
          results = results.find(v => (v.has("learn") and ((v->learn == thisHaystackCur.replace("@C", "slot:").replace("@S", "sep:").replace(".", "/")) or (v->learn.toStr == "equip:/"+thisHaystackCur.replace("@", "")))) or (v->id == thisHaystackCur.toStr.replace("@", "").parseRef)) //.merge({connRef: haystackConnRef})

        if (results == null)
          return null

        return results.merge({connRef: haystackConnRef, previousLearn: row["previousLearn"]})
      end).findAll(v => v != null)
    end
  end

  dropTarget = readById(dropTarget, false)

  //vars needed
  dropNav: if(dropTarget != null) dropTarget.finNavMetaWhoAmI else "topLevel"
  navMetaList: read(navMeta)->equipPath[1..-1].split("/").map(r => reFind(r"[a-zA-Z_0-9]+", r)) //.findAll(v => dropTarget == null or not v.startsWith("[") or dropTarget.has(v[1..-2]+"Ref"))
  dropPos: navMetaList.index(dropNav)
  stopLoop: true
  action: ""
  msg: ""
  isConn: false
  itemMoving: false
  addingConnPt: false
  itemToMoveList: []
  connRefType: ""
  connPtsAdded: null
  connObjsAdded: []
  tempConnPoint: {}
  refreshStr: ""
  disList: []

  if(dragTargets == null) do
    msg = toLocale("finStackMobileExt::incorrectItemsForEquipTreeErr")
    dragTargets = []
  end

  /*
    TODO:
    Create action and message for confirmation form that includes all actions to take.
      EX: drop tagBundle, schedule, and 2 conns -> make action that includes application of tag
          bundle, schedule, and first connector.

    See dropActionScheduleTree for reference on how to implement.

    Also add tuning policy drops when tree is added.
  */
  //begin drop action
  dragTargets.each(item =>
  do
    dragNav: item.finNavMetaWhoAmI
    newProps: {}

    //something from equipTree
    if(dragNav != null and not (item.has("connPointDiscovery") or item.has("axSlotPath") or item.has("learn") or item.has("modbusAdd")) and haystackConnRef == null) do
      stopLoop = false
      dragPos: eachWhile(navMetaList) (x, i) => if(x == dragNav) i

      if (userIsOp)
        msg = toLocale("finStackMobileExt::cannotMoveItem").replace("{item}", dragNav)
      else if ((dropPos - dragPos == -1) or (dropNav == "equip" and dragNav == "equip")) do
        itemMoving = true
        itemToMoveList = itemToMoveList.add(item)
        action = action + "{item: "+item->id.toAxonCode+", target: "+dropTarget->id.toAxonCode+"},"
        msg = toLocale("finStackMobileExt::moveItemToTarget").replace("{item.dis}", item.dis).replace("{target}", dropTarget.dis)
      end
      else
      do
        msg = toLocale("finStackMobileExt::incorrectNavTreeDropMsg")

        if (dragNav == "equip")
          msg = msg.replace("{childNode}", dragNav).replace("{parentNode}", navMetaList[dragPos - 1])
        else
        do
          i: msg.indexr("Node}") + 4

          msg = msg[0..i].replace("{childNode}", dragNav).replace("{parentNode}", navMetaList[dragPos - 1])
      end
    end //end equipTree

    //something from tagBundles
    else if(item.has("tagBundle"))
    do
      finApplyTagBundle(item, [dropTarget->id])
    end

    // something from Tuning Policy Tree
    else if (item.has("connTuning"))
    do
      newProps = {connTuningRef: item->id}

      if (dropNav == "point")
      do
        msg = toLocale("finStackMobileExt::applyTuningPolicyConfirmation").replace("{policyName}", item.dis).replace("{targetName}", dropTarget.dis)
        action = "readById("+dropTarget->id.toAxonCode+").diff("+newProps.toAxonCode+").commit"
      end
      else
      do
        msg = toLocale("finStackMobileExt::tuningPolicyApplyRestrictions")
        action = ""
      end
    end

    //something from schedules
    else if(item.has("schedule") and haystackConnRef == null)
    do
      newProps = {scheduleRef: item->id}

      //if point, figure out kind and schedulable stuff
      if(dropNav == "point" and item->kind == dropTarget->kind) do
        if(not dropTarget.has("schedulable")) newProps = newProps.set("schedulable", 15)
      end

      action = "readById("+dropTarget->id.toAxonCode+").diff("+newProps.toAxonCode+").commit"

      //create messages
      if(dropNav == "point" and item->kind != dropTarget->kind)
      do
        msg = toLocale("finStackMobileExt::scheduleAndPointNotSame").replace("{scheduleKind}", item->kind).replace("{pointKind}", dropTarget->kind)
        action = ""
      end
      else if(dropTarget.has("scheduleRef"))
        msg = toLocale("finStackMobileExt::confirmReplaceAssignedSchedule")
          .replace("{curSchedule}", dropTarget->scheduleRef.readById.dis)
          .replace("{dropTarget}", dropTarget.dis)
          .replace("{newSchedule}", item.dis)
      else
        msg = toLocale("finStackMobileExt::confirmAddSchedule").replace("{scheduleName}", item.dis).replace("{dropTarget}", dropTarget.dis)
    end //end schedules

    //something from connectors
    else if(item.names.find(v => v.contains("Conn")) != null and dragNav != "point" and not finConnectorTypes().isEmpty)
    do
      singleConn: false
      uniqueConns: null
      isConn = true

      //find matching connRef types
      connTag: item.names.find(v => v.contains("Conn"))
      connRefType = finConnectorTypes().find(v => connTag.contains(v->name))->name + "ConnRef"
      newProps = newProps.set(connRefType, item->id)

      //find number of unique matching connRefs
      if(dropNav == "point" and dropTarget.has(connRefType)) do
        action = "readById("+dropTarget->id.toAxonCode+").diff("+newProps.toAxonCode+").commit"
        msg = toLocale("finStackMobileExt::confirmReplaceConnector").replace("{curConn}", dropTarget[connRefType].readById.dis).replace("{newConn}", item.dis)
        singleConn = true
      end else do
        uniqueConns = readAll(parseFilter(dropNav+"Ref == "+dropTarget->id.toAxonCode+" and "+connRefType)).unique(connRefType)
        if(uniqueConns.size == 1) singleConn = true
      end

      if(singleConn and action == "") do
        action = "readAll("+dropNav+"Ref == "+dropTarget->id.toAxonCode+" and "+connRefType+").each x => x.diff("+newProps.toAxonCode+").commit"

        //need to get connRefs in point if not on equip
        msg = toLocale("finStackMobileExt::confirmReplaceAllRefToConn")
          .replace("{curConnType}", connRefType.replace("ConnRef", ""))
          .replace("{curConn}", uniqueConns[0][connRefType].readById.dis)
          .replace("{newConn}", item.dis)
      end
    end //end connectors

    //new connector point
    else if(not item.has("learnItem") and (item.has("connPointDiscovery") or item.has("learn") or item.has("axSlotPath") or haystackConnRef != null or item.has("connRef")))
    do
      connPoint: if(haystackConnRef != null) item.merge({refInHaystackConn: item->id.toStr, -id, -axSlotPath, -axType}) else item.merge({-id, -tempId, -discoverTime, -is, -mod, -connPointDiscovery, -returnedToUi, -fromTree, -modbusAdd})
      removeList: []

      connPoint = stripUncommittable(connPoint) // remove transient tags
      connRec: try readById(item->connRef, false) catch null

      if (connRec != null)
        connRefType = connRec.names.find(v => v.endsWith("Conn")) + "Ref"

      // mark tags that are null for removal
      connPoint.names.each x =>
      do
        if (connPoint[x] == null)
          removeList = removeList.add(x)
      end

      // remove marked tags
      if (not removeList.isEmpty)
        connPoint = connPoint.toGrid.removeCols(removeList)[0]

      if(not item.has("point")) do

        if(dropTarget == null)
          dropTarget = {id:@folderPath:equip: } //finFindNonDbRec([@folderPath:equip:])[0]

        startLearn: item["learn"]

        if (startLearn == null) // the id within the haystack server
          startLearn = item["id"].toAxonCode

        if(dropPos == null and navMetaList.index(dragNav) == 0)
          connObjsAdded = connObjsAdded.add("finCreateHaystackDb(["+item->connRef.toAxonCode+"], "+startLearn.toStr.toAxonCode+", false, true, null, " + item["previousLearn"].toAxonCode + ")")
        else if((dragNav == "equip" and dropNav == "equip") or (dropPos != null and dropPos < navMetaList.index(dragNav)))
          connObjsAdded = connObjsAdded.add("finCreateHaystackDb(["+item->connRef.toAxonCode+"], "+startLearn.toStr.toAxonCode+", false, true, "+dropTarget->id.toAxonCode+", " + item["previousLearn"].toAxonCode +")")
        else
          msg = dragNav + " can't be added to " + dropNav + "."
      end
      else if(dropNav == "equip") do
        addingConnPt = true
        connPrefix: readById(item->connRef).names.find(v => v.endsWith("Conn"))[0..-5]

        tempConnPoint = connPoint.merge({
          siteRef: dropTarget->siteRef,
          floorRef: dropTarget->floorRef,
          equipRef: dropTarget->id,
          is: if (connPoint.has("is")) connPoint->is else "",
          navName: try connPoint->navName catch connPoint->dis,
          -dis, -disMacro, -mod, -is, -learn, aux, -scheduleGrid, -previousLearn,
          tz: if(dropTarget.has("tz")) dropTarget->tz else if(dropTarget->siteRef.readById.has("tz")) dropTarget->siteRef->tz else now().tz
        }).set(connPrefix + "ConnRef", item->connRef)

        if (tempConnPoint.has(connPrefix + "Cur"))
          tempConnPoint = tempConnPoint.set("cur", marker())

        if (tempConnPoint.has(connPrefix + "Write"))
        do
          tempConnPoint = tempConnPoint.set("writable", marker())

          if (connRec != null and connRec["defaultWriteLevel"] != null)
            tempConnPoint = tempConnPoint.set(connRefType.replace("ConnRef", "WriteLevel"), connRec->defaultWriteLevel)
        end

        if (tempConnPoint.has(connPrefix + "His") or tempConnPoint.names.find(prop => prop.endsWith("His")) != null)
          tempConnPoint = tempConnPoint.merge({his, -aux})

        //remove unit if null or ""
        if(tempConnPoint.has("unit"))
        do
          if (tempConnPoint->unit == "" or tempConnPoint->unit == null) tempConnPoint = tempConnPoint.merge({-unit})
          else if (tempConnPoint->unit == "\$") tempConnPoint = tempConnPoint.merge({unit: "DOLLAR_SIGN"})
        end

        if(not (tempConnPoint.has("sp") or tempConnPoint.has("cmd") or tempConnPoint.has("sensor")))
          tempConnPoint = tempConnPoint.merge({sensor})

        //remove old conn tags when importing via haystack connector
        if (connPrefix == "haystack") do
          tempConnPoint.each((val, t) => do
            tag : reFind(r"^(?!haystack).*(?:Cur|Write|His|ConnRef)$", t)
            if (tag != null) tempConnPoint = tempConnPoint.remove(tag)
          end)

          blacklistedTags: {-curConvert, -writeConvert, -curTracksWrite, -hisConvert, -hisMode, -hisTotalized, -hisFunc, -hisCollectInterval, -hisCollectCov}
          tempConnPoint = tempConnPoint.merge(blacklistedTags)
        end

        if(connPtsAdded == null)
          connPtsAdded = "commit([diff(null, "+tempConnPoint.toAxonCode+", {add})"
        else
          connPtsAdded = connPtsAdded + ", diff(null, "+tempConnPoint.toAxonCode+", {add})"

        disList = disList.add(connPoint.dis)
        msg = toLocale("finStackMobileExt::confirmAddConnPt").replace("{ptDis}", connPoint.dis).replace("{dropTarget}", dropTarget.dis)
      end else msg = toLocale("finStackMobileExt::connPtsMustBeDroppedEquip")
    end
    else do
      stopLoop = true
      msg = toLocale("finStackMobileExt::incorrectItemsForEquipTreeErr")
    end //end all else

    //break loop early if conn, schedule, or tuning
    if(stopLoop) return 0
    else return null
  end) //end itemLoop

  if(itemMoving)
  do
    nodesToRefresh: []
    hasHistory: false

    itemToMoveList.each(r =>
    do
      if (r.has("his") or (not r.has("point") and readCount(parseFilter("point and his and " + finNavMetaWhoAmI(r) + "Ref == " + r->id.toAxonCode)) > 0))
        hasHistory = true

      if(r[navMetaList[dropPos] + "Ref"] != null)
        nodesToRefresh = nodesToRefresh.add(r[navMetaList[dropPos] + "Ref"])
    end)

    action = "(["+action[0..-2]+"]).dbNavMove"
    refreshStr = "window.app.RefreshBuilderTreeNodeForId('"+dropTarget->id.toAxonCode+"');"
    nodesToRefresh.unique.each node => refreshStr = refreshStr + "window.app.RefreshBuilderTreeNodeForId('"+node.toAxonCode+"');"

    // node empty, referesh parent first
    if (readCount(parseFilter(dropNav + "Ref == "+dropTarget->id.toAxonCode)) == 0)
    do
      if (dropPos > 0)
        refreshStr = "window.app.RefreshBuilderTreeNodeForId('"+dropTarget[navMetaList[dropPos - 1]+"Ref"].toAxonCode+"'); setTimeout(function() { try {"+refreshStr+"} catch (err) {}}, 500);"
      else // refresh root
        refreshStr = "window.app.RefreshBuilderTreeNodeForId('@folderPath:equip:'); setTimeout(function() { "+refreshStr+" }, 500);"
    end

    if(itemToMoveList.size > 1)
      msg = toLocale("finStackMobileExt::moveEquipTree").replace("{dropTarget}", dropTarget.dis)

    if (hasHistory)
    do
      refreshStr = [
        "function checkJobStatus(jobHandle) {",
          "var promise;",
          "if (jobHandle === undefined) {",
            "promise = finstack.evalAll(['jobStatusAll().find(v => v->dis.startsWith(\"[finRewriteHisTzCommit\") and v->started > "+now().toAxonCode+")']);",
          "} else {",
            "promise = finstack.evalAll(['jobStatus(\"'+jobHandle+'\")[0]']);",
          "}",
          "promise.then(function(event) {",
            "var jobStat = event.result[0].toObj(false, false, true);",
            "var isDone = jobStat ? jobStat['jobStatus'].startsWith('done') : null;",
            "if (isDone || isDone === null) {",
              refreshStr,
              "window.top.app.HideLoader();",
            "} else {",
              "window.top.app.HideLoader();",
              "window.top.app.ShowLoader(languageManager[\"updatingHisPtsTz\"]);",
              "setTimeout(function(){ checkJobStatus(jobStat['handle']) }, 2000);",
            "}",
          "});",
        "}",
        "window.top.app.ShowLoader(languageManager[\"updatingHisPtsTz\"]);",
        "checkJobStatus();"
      ].concat("")
    end
  end
  else if(connPtsAdded != null or not connObjsAdded.isEmpty)
  do
    refreshStr = "window.app.RefreshBuilderTreeNodeForId('"+dropTarget->id.toAxonCode+"');"
    // drop target has no children, need to refresh its parent node first
    if (readCount(parseFilter(dropNav + "Ref == "+dropTarget->id.toAxonCode)) == 0)
    do
      if (dropPos > 0)
        refreshStr = "window.app.RefreshBuilderTreeNodeForId('"+dropTarget[navMetaList[dropPos - 1]+"Ref"].toAxonCode+"'); setTimeout(function() { try {"+refreshStr+"} catch (err) {}}, 750);"
      else
        refreshStr = "window.app.RefreshBuilderTreeNodeForId('@folderPath:equip:'); setTimeout(function() { "+refreshStr+" }, 500);"
    end
    else
      refreshStr = refreshStr + " window.app.RefreshBuilderGridAt(0, 'panel');"

    if (connPtsAdded != null)
    do
      action = "finAddPointInfo("+finBase64Encode(connPtsAdded+"])").toAxonCode+")"

      if (haystackConnRef == null or haystackConnRef == "undefined")
        refreshStr = refreshStr + (if(not refreshStr.contains("RefreshBuilderGridAt")) " window.app.RefreshBuilderGridAt(0, 'panel');" else "") +" setTimeout(function() { try { window.app.RefreshBuilderGridAt(0, 'discover'); } catch (err) {}}, 750);" //; window.app.RefreshBuilderGridAt(0, 'discover')

      if (addingConnPt)
        refreshStr = [
          "function checkJobStatus(jobHandle) {",
            "var promise;",
            "if (jobHandle === undefined) {",
              "promise = finstack.evalAll(['jobStatusAll().find(v => v->dis.startsWith(\"finAddPointInfo(\") and v->started > "+now().toAxonCode+")']);",
            "} else {",
              "promise = finstack.evalAll(['jobStatus(\"'+jobHandle+'\")[0]']);",
            "}",
            "promise.then(function(event) {",
              "var jobStat = event.result[0].toObj(false, false, true);",
              "var isDone = jobStat ? jobStat['jobStatus'].startsWith('done') : null;",
              "if (isDone || isDone === null) {",
                refreshStr,
                "finstack.eval('readAll(point and "+dropNav+"Ref == "+dropTarget->id.toAxonCode+" and "+connRefType+").findAll(v => v->mod >= "+curTime.toAxonCode+")').then(function(event)",
                "{",
                  "var idArry = event.result.gridRows.map(x => x.id);",
                  "window.app.InitBatchRecordEditor('"+dropTarget->id.toAxonCode+"', 'update', idArry, function() { window.app.RefreshBuilderTreeNodeForId('"+dropTarget->id.toAxonCode+"'); }, finstack);",
                "});",
                "window.top.app.HideLoader();",
              "} else {",
                "window.top.app.HideLoader();",
                "window.top.app.ShowLoader(languageManager[\"addingPoints\"] + \"...\");",
                "setTimeout(function(){ checkJobStatus(jobStat['handle']) }, 1000);",
              "}",
            "});",
          "}",
          "window.top.app.ShowLoader(languageManager[\"addingPoints\"] + \"...\");",
          "checkJobStatus();"
        ].concat("")

      if (dragTargets.findAll(v => v.has("learn") or v.has("axSlotPath") or v.has("connPointDiscovery")).size > 1)
      msg = toLocale("finStackMobileExt::confirmAddConnPts").replace("{dropTarget}", dropTarget.dis)
    end
    else //connObjectsAdded
    do
      if (not refreshStr.contains("RefreshBuilderGridAt"))
        refreshStr = refreshStr + " window.app.RefreshBuilderGridAt(0, 'panel');"

      action = "("+connObjsAdded.toAxonCode+").each x => eval(x)"

      if(dropTarget->id != @folderPath:equip:) msg = toLocale("finStackMobileExt::addHaystackItemsToTarget").replace("{target}", dropTarget.dis)
      else msg = toLocale("finStackMobileExt::addHaystackNavItemToDB").replace("{navItem}", navMetaList[0])
    end
  end

  //if conn or schedule, show warning if only 1 conn to be replaced, else show update connectors
  if(not action.isEmpty())
  do
    if (runAsJob)
    do
      msg = toLocale("finStackMobileExt::confirmAddConnPts").replace("{dropTarget}", dropTarget.dis)
      action = "jobRun("+action+")"
    end
    else if (disList.size > 5) msg = toLocale("finStackMobileExt::confirmAddConnPts").replace("{dropTarget}", dropTarget.dis)
    else if (disList.size > 1) msg = toLocale("finStackMobileExt::confirmAddConnPt").replace("{ptDis}", disList[0..-2].add("and " + disList[-1]).concat(", ")).replace("{dropTarget}", dropTarget.dis)

    finFormConfirmChangesAlert(action, msg, refreshStr)
  end
  else if(isConn and action.isEmpty()) finFormUpdateConnectors(dropTarget->id, null, {connType: connRefType.replace("ConnRef", ""), conn: dragTargets[0]->id})
  else if(not isConn and not msg.isEmpty()) finFormAlertOk(toLocale("finStackExt::regError"), msg)
end


def ​

func:dropActionFolderPaths ​

dropActionFolderPaths(dragTargets, dropTarget, treeTag) ​

Axon function


meta ​

deffunc:dropActionFolderPaths
isfunc
liblib:finStackMobile
namedropActionFolderPaths
overridable✓
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(dragTargets, dropTarget, treeTag) => do
  treeTagFilters:{
    graphics: "fin5", //was graphicOn
    programs: "programOn",
    schedules: "schedule",
    template: "templateOn,finTemplate"
  }

  dragTargets = try dragTargets.map(r => r.replace("@", "").parseRef) catch null
  dropIdStr: dropTarget.toStr
  folderPath: ""

  tagStr: treeTagFilters[treeTag]
  folderTag: ""

  if(tagStr == null)
  do
    tagStr = treeTag
    folderTag = treeTag+"Folder"
  end
  else
    folderTag = (if(treeTag.endsWith("s")) treeTag[0..-2] else treeTag) +"Folder"

  //build folderpath
  if(dropIdStr.startsWith("folderPath"))
    folderPath = dropIdStr.finIdToFolderPath()
  else
  do
    folderRec: readById(dropTarget)
    folderPath = if(folderRec["folderPath"] != "" and folderRec["folderPath"] != null) folderRec->folderPath + "/" + folderRec.dis else folderRec.dis
  end

  //move each dragged item to new folderPath
  if(dragTargets != null) do
    finFindNonDbRec(dragTargets).each((x,i) =>
    do
      possibleTags: tagStr.split(",")
      isPartOfTree: if (possibleTags.size == 1) x.has(tagStr) else possibleTags.find(v => x.has(v)) != null

      if(isPartOfTree or x.has(folderTag) or (x.has("isFolder") and x->id.toStr.startsWith("folderPath:"+treeTag)))
        folderPathMove(x->id, folderPath, treeTag,(if(not dropIdStr.startsWith("folderPath") and readById(dropTarget, false) != null and readById(dropTarget).has("emptyFolder")) dropTarget else null))
    end)
  end //end moving items
end //end func


def ​

func:dropActionSavedFiltersTree ​

dropActionSavedFiltersTree(dragTargets, dropTarget) ​

Determines and takes the appropriate action for when an item is dropped onto an item within the saved filter tree in the DB Builder app.

Supports the following items dropped onto the equip tree:

  • tagBundles: First the saved filter is queried, then all items returned by the save query are ran against the tag bundles dropped onto the saved query.

dragTargets - A list of ids as strings. (The items dropped)

dropTarget - The id of the target for the drop action. (The target of the dragTargets)


meta ​

constructdropActionSavedFiltersTree([read(tagBundle)->id.toAxonCo...
deffunc:dropActionSavedFiltersTree
isfunc
liblib:finStackMobile
namedropActionSavedFiltersTree
overridable✓
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(dragTargets, dropTarget) => do
  dropIdStr: dropTarget.toStr
  dragRecords: readByIds(dragTargets.map(r => r[1..-1].parseRef), false)

  /*
    this may be able to be removed. default logic now
    assigns dropActionFolderPaths to items identified as folders
  */
  // if dropTarget is a folder
  if (dropIdStr.startsWith("folderPath") or readByIds([dropTarget]).has("emptyFolder")) do
    folderPath: ""

    // folder with items
    if (dropIdStr.startsWith("folderPath"))
      folderPath = dropIdStr.finIdToFolderPath()

    // empty folder
    else
    do
      folderRec: readById(dropTarget)
      folderPath = if(folderRec["folderPath"] != null) folderRec->folderPath + "/" + folderRec.dis else folderRec.dis
    end

    // move items
    if (dragTargets != null)
    do
      finFindNonDbRec(dragTargets).each((x,i) => do
        if (x.has("savedQueryFilter") or (x.has("isFolder") and x->id.toStr.startsWith("folderPath:savedQueryFilter")))
        do
          emptyFolderId: null

          if (not dropIdStr.startsWith("folderPath") and readById(dropTarget, false) != null and readById(dropTarget).has("emptyFolder"))
            emptyFolderId = dropTarget

          folderPathMove(x->id, folderPath, "savedQueryFilter", emptyFolderId)
        end
      end)
    end
  end

  // dragTarget is a tag bundle
  else do
    dragTargets = try finFindNonDbRec(dragTargets) catch null
    dropTarget = if (dropTarget.toStr.startsWith("savedQueryFilter")) finFilteredFuncEval(savedQueryFilter, filterString).find(v => v->id == dropTarget) else readById(dropTarget, false)

    dropTargetFilterResults: dropTarget->filterString.parseFilter.readAll

    // tuning policy
    if (dragTargets.toGrid.has("connTuning"))
    do
      dragTargets = dragTargets.findAll(v => v.has("connTuning"))

      if (dragTargets.size > 1)
        return finFormAlertOk(toLocale("finStackExt::warning"), toLocale("finStackMobileExt::pointsAndConnsCanHaveOnlyOnePolicy"))

      if (dropTargetFilterResults.size > 0)
      do
        results: dropTargetFilterResults.finGridFilter(point or conn)

        if (results.size > 0)
          finFormConfirmChangesAlert(
            "readByIds("+results.colToList("id").toAxonCode+").toRecList.map(r => r.diff({connTuningRef: "+dragTargets[0]->id.toAxonCode+"})).commit",
            toLocale("finStackMobileExt::applyTuningPolicyToSavedFilter").replace("{policyName}", dragTargets[0].dis).replace("{savedFilter}", dropTarget.dis)
          )
        else
          finFormAlertOk(toLocale("finStackExt::warning"), toLocale("finStackMobileExt::savedFilterResultsInvalidForPolicy").replace("{savedFilter}", dropTarget.dis).replace("{policyName}", dragTargets[0].dis))

      end
      else finFormAlertOk(toLocale("finStackExt::warning"), toLocale("finStackMobileExt::savedFilterNoResults").replace("{savedFilter}", dropTarget.dis))
    end

    // tag bundles
    else
    do
      if (dragTargets != null) dragTargets = dragTargets.findAll(v => v.has("tagBundle"))

      if (dropTargetFilterResults.size > 0)
        finFormConfirmChangesAlert(
          "finApplyTagBundle("+dragTargets.toAxonCode+", "+dropTargetFilterResults.colToList("id").toAxonCode+")",
          toLocale("finStackMobileExt::applyTagBundleToSavedFilter")
            .replace("{tagBundle}", (if(dragTargets != null and dragTargets.size > 1) "tag bundles" else if (dragTargets != null) dragTargets[0].dis else "null"))
            .replace("{savedFilter}", dropTarget.dis)
        )
      else
      finFormAlertOk(toLocale("finStackExt::warning"), toLocale("finStackMobileExt::savedFilterNoResults").replace("{savedFilter}", dropTarget.dis))
    end
  end

  // do nothing otherwise
end


def ​

func:dropActionScheduleTree ​

dropActionScheduleTree(dragTargets, dropTarget, connRefTag: null) ​

Determines and takes the appropriate action for when an item is dropped onto an item within the schedule tree in the DB Builder app.

Supports the following items dropped onto the schedule tree:

  • connectors: Assigns or replaces the scheduleRef on each connector to the target schedule.
  • equip tree items: Assigns or replaces the scheduleRef on each equip tree item to the target schedule. If the equipTree item is a point, only matching point and schedule types will be updated.

dragTargets - A list of ids as strings. (The items dropped)

dropTarget - The id of the target for the drop action. (The target of the dragTargets)


meta ​

constructdropActionScheduleTree([read(equip)->id.toAxonCode], rea...
deffunc:dropActionScheduleTree
isfunc
liblib:finStackMobile
namedropActionScheduleTree
overridable✓
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(dragTargets, dropTarget, connRefTag: null) => do
  try do
    if (dragTargets.isEmpty)
      return "empty"

    dropIdStr: dropTarget.toStr

    // folder path
    folderPath: removeMarker()
    folderRec: null
    if (dropIdStr.startsWith("folderPath") or readByIds([dropTarget]).has("emptyFolder")) do
      if(dropIdStr.startsWith("folderPath"))
        folderPath = dropIdStr.finIdToFolderPath()
      else do
        folderRec = readById(dropTarget, false)
        folderPath = if (folderRec != null and folderRec["folderPath"] != null and not folderRec["folderPath"].isEmpty) folderRec->folderPath + "/" + folderRec.dis else folderRec.dis
      end
    end

    // schedule from connector
    if (connRefTag != null) do
      connType: connRefTag.replace("ConnRef", "")

      dragTargets.each(item => do
        connRef: item["connRef"][1..-1].parseRef
        learnPath: if (item.has("learn")) item["learn"] else item["parentLearn"]

        if (learnPath != null) do
          if (learnPath.startsWith("nav:")) learnPath = parseRef(learnPath)
          else if (learnPath.startsWith("@")) learnPath = parseRef(learnPath[1..-1])
        end

        if (item.has("learn")) do
          call(connType+"Learn", [connRef, learnPath]).each r => do
            if (r.has("schedule"))
              try diff(null, r.merge({folderPath: folderPath}.set(connRefTag, connRef)), {add}).commit catch "skipping"
          end
        end
        else do

          scheduleDict: call(connType+"Learn", [connRef, learnPath]).find(v => v.dis == item.dis)
          if (scheduleDict == null)
            throw "Schedule not found in connector"

          diff(null, scheduleDict.merge({folderPath: folderPath}.set(connRefTag, connRef)), {add}).commit
        end
      end)

      if (folderRec != null)
        folderPathDelete(folderRec->id)
    end
    // folder, update folder path on schedule
    else if (folderPath != removeMarker()) do
      dragTargets = try finFindNonDbRec(dragTargets) catch null

      if(dragTargets != null) do
        dragTargets.each((x,i) => do
          if(x.toGrid.has("schedule") or (x.has("isFolder") and x->id.toStr.startsWith("folderPath:schedules")))
            folderPathMove(x->id, folderPath, "schedules", (if(not dropIdStr.startsWith("folderPath") and readById(dropTarget).has("emptyFolder")) dropTarget else null))
        end)
      end
    end
    // assign schedule to dragTargets (from equip tree)
    else
    do
      dragTargets = try finFindNonDbRec(dragTargets) catch null
      dropTarget = readById(dropTarget, false)
      action: ""
      noMatchMsg: toLocale("finStackMobileExt::scheduleAndManyPointNotSame").replace("{target}", dropTarget.dis).replace("{targetKind}", dropTarget->kind)
      noMatchList: []
      addMsg: toLocale("finStackMobileExt::scheduleAssignedToManyPts").replace("{scheduleName}", dropTarget.dis)
      addList: []
      replaceMsg: toLocale("finStackMobileExt::scheduleAssignedToManyPts").replace("{scheduleName}", dropTarget.dis)
      replaceList: []
      tbList: []
      tbMsg: toLocale("finStackMobileExt::multipleTagBundlesApplied").replace("{item}", dropTarget.dis)
      msg: []
      refreshAction: ""

      dragTargets.each item => do
        dragNav: item.finNavMetaWhoAmI
        newProps: {}

        //if a conn or from equip tree
        if(dragNav != null or item.names.find(v => v.contains("Conn")) != null) do
          newProps = {scheduleRef: dropTarget->id}

          //if point, figure out kind and schedulable stuff
          if(dragNav == "point" and item->kind == dropTarget->kind and not item.has("schedulable"))
            newProps = newProps.set("schedulable", 15)

          //create form messages
          if(dragNav == "point" and item->kind != dropTarget->kind)
            noMatchList = noMatchList.add(item.dis)
          else if(item.has("scheduleRef")) do
            action = action + "{id:"+ item->id.toAxonCode + ", newProps:"+newProps.toAxonCode+"},"
            replaceList = replaceList.add(item.dis)
            refreshAction = "window.app.RefreshBuilderGridAt(0, 'panel')"
          end else do
            refreshAction = "window.app.RefreshBuilderGridAt(0, 'panel'); window.app.RefreshBuilderGridAt(0, 'discover')"
            action = action + "{id:"+ item->id.toAxonCode + ", newProps:"+newProps.toAxonCode+"},"
            addList = addList.add(item.dis)
          end
        end //end from equip or connector tree

        else if(item.has("tagBundle")) do
          action = item.toAxonCode + ","
          //finApplyTagBundle(item, [dropTarget->id])

          tbList = tbList.add(item->dis)
        end
      end//end loop

      if(not action.isEmpty())
        action = "["+action[0..-2] + "].each x => if(not x.has(\"tagBundle\")) readById(x->id).diff(x->newProps).commit() else finApplyTagBundle(x, ["+dropTarget->id.toAxonCode+"])"

      //if nothing in all lists
      if(noMatchList.isEmpty and addList.isEmpty and replaceList.isEmpty and tbList.isEmpty)
        finFormAlertOk(toLocale("finStackExt::regError"), toLocale("finStackMobileExt::scheduleTreeIncorrectDrop"))
      else do
        if(not addList.isEmpty) msg = msg.add(addMsg).add({nameList: addList, changing})
        if(not replaceList.isEmpty) msg = msg.add(replaceMsg).add({nameList: replaceList, changing})
        if(not noMatchList.isEmpty) msg = msg.add(noMatchMsg).add({nameList: noMatchList})
        if(not tbList.isEmpty) msg = msg.add(tbMsg).add({nameList: tbList, changing})

        finFormConfirmChangesAlert(action, msg, refreshAction)
      end
    end
  end catch (err) finFormAlertOk("Error", err.dis)
end


def ​

func:dropActionTagBundlesTree ​

dropActionTagBundlesTree(dragTargets, dropTarget, jsAction: []) ​

Determines and takes the appropriate action for when an item is dropped onto an item within the tagBundle tree in the DB Builder app.

Anything can be dropped onto the tagBundle tree. Every item is checked against the target bundle's allowFilter and tags are applied accordingly.

dragTargets - A list of ids as strings. (The items dropped)

dropTarget - The id of the target for the drop action. (The target of the dragTargets)


meta ​

constructdropActionTagBundlesTree([read(equip)->id.toAxonCode], r...
deffunc:dropActionTagBundlesTree
isfunc
liblib:finStackMobile
namedropActionTagBundlesTree
overridable✓
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(dragTargets, dropTarget, jsAction: []) => do
  dragTargets = try dragTargets.map(r => r.replace("@", "").parseRef) catch null
  dropIdStr: dropTarget.toStr

  // folders
  if(dropIdStr.startsWith("folderPath") or readByIds([dropTarget], false).has("emptyFolder")) do
    folderPath: ""

    if(dropIdStr.startsWith("folderPath"))
      folderPath = dropIdStr.finIdToFolderPath()
    else do
      folderRec: readById(dropTarget)
      folderPath = if(folderRec["folderPath"] != null) folderRec->folderPath + "/" + folderRec.dis else folderRec.dis
    end

    if(dragTargets != null) do
      finFindNonDbRec(dragTargets).each((x,i) => do
        if(x.has("tagBundle") or (x.has("isFolder") and x->id.toStr.startsWith("folderPath:tagBundle")))
          folderPathMove(x->id, folderPath, "tagBundle", (if(not dropIdStr.startsWith("folderPath") and readById(dropTarget, false) != null and readById(dropTarget).has("emptyFolder")) dropTarget else null))
      end)
    end
  end

  //everythign else
  else do
    // tag_bundle as id
    dropTarget = if(dropIdStr.startsWith("tagBundle")) finFilteredFuncEval(tagBundleFunc, addTags or removeTags).find(v => v->id == dropTarget) else readById(dropTarget, false)

    //handle saved filters
    if(dragTargets != null and finFindNonDbRec(dragTargets).toGrid.has("filterString")) do//dragTargets.toRecList.has("filterString")) do
      newTargs: []

      //dragTargets.toRecList.each x => do
      finFindNonDbRec(dragTargets).each x => do
        if(not x.has("filterString")) newTargets = newTargets.add(x->id)
        else readAll(x->filterString.parseFilter).each y => newTargs = newTargs.add(y->id)
      end

      dragTargets = if(newTargs.isEmpty()) null else newTargs.unique
    end

    if(dragTargets != null) //finApplyTagBundle(dropTarget, dragTargets)
      finFormConfirmChangesAlert("finApplyTagBundle("+dropTarget.toAxonCode+", "+dragTargets.toAxonCode+")", toLocale("finStackMobileExt::applyTagBundleToSavedFilter").replace("{tagBundle}", dropTarget.dis).replace("{savedFilter}", (if(dragTargets != null and dragTargets.size > 1) toLocale("finStackMobileExt::targets") else if (dragTargets != null) dragTargets[0].readById.dis else "null")), jsAction.concat(""))
  end
end


def ​

func:finAddBuilderProps ​

finAddBuilderProps(treeDataGrid, treeDis, branchDis) ​

Axon function


meta ​

deffunc:finAddBuilderProps
isfunc
liblib:finStackMobile
namefinAddBuilderProps

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function


def ​

func:finAddPointInfo ​

finAddPointInfo(newRefs) ​

Axon function


meta ​

deffunc:finAddPointInfo
isfunc
liblib:finStackMobile
namefinAddPointInfo
overridable✓
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(newRefs) => do
  if (newRefs.isStr)
  do
    newRefs = finBase64Decode(newRefs).eval
  end

  newRefs.each x => do
    propsToAdd: {disMacro: "\$equipRef \$navName", refInHaystackConn: removeMarker()}

    if (x.has("unit") and x->unit == "DOLLAR_SIGN")
      propsToAdd = propsToAdd.merge({unit: "\$"})

    if(x.has("writable") and not x.has("haystackConnRef") and not x.has("actions"))
      propsToAdd = propsToAdd.merge({actions: finPointActions(x->kind).gridToZinc})
    else if((x.has("writable") or x.has("schedule")) and x.has("haystackConnRef")) do
      path: []

      if(x["haystackCur"] != null)
      do
        path = x->haystackCur.replace("@", "").split(".")

        if(path[0] == "C")
          path = path.remove(0).insert(0, "slot:")
        else if (path[0] == "S")
          path = path.remove(0).insert(0, "sep:")
      end
      else do
        path = [x->refInHaystackConn.toStr]
      end

      results: null

      if(path[0].startsWith("sep:") or path[0].startsWith("slot:")) do
        if(path.size > 2) path = path[0..-2].concat("/")
        else path = path[0] + "/"

        results = finHaystackLearn(x->haystackConnRef, path).find(v => v.has("haystackCur") and v->haystackCur == x->haystackCur)
      end else
        results = try haystackRead(x->haystackConnRef, parseFilter("id == @" + path[0]), false) catch {}

      if(results == null) do
        if(x["haystackCur"] != null and (x->haystackCur.startsWith("S") or x->haystackCur.startsWith("C")))
          results = haystackCall(x->haystackConnRef, "read", {filter: "id == @" + x->refInHaystackConn})[0]
        else
          results = haystackCall(x->haystackConnRef, "read", {filter: "id == @" + (try x->haystackCur catch x->refInHaystackConn)})[0]
      end

      if(results.has("scheduleGrid") and not x.has("scheduleGrid"))
        propsToAdd = propsToAdd.merge({scheduleGrid: results->scheduleGrid})
      if(results.has("actions") and not x.has("actions"))
        propsToAdd = propsToAdd.merge({actions: results->actions})
    end

    x.diff(propsToAdd).commit
    readById(x->id).diff({-refInHaystackConn}, {force}).commit
  end

  newRefs.toGrid.watchOpen("New Point Added Wacth")
  watchClose("New Point Added Wacth")
end


def ​

func:finAlarmSettingsForm ​

finAlarmSettingsForm(pollRate: 0, disableNotifications: true) ​

Axon function


meta ​

deffunc:finAlarmSettingsForm
isfunc
liblib:finStackMobile
namefinAlarmSettingsForm
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(pollRate: 0, disableNotifications: true) => do
  body: [
    {name: "pollRate", editorType: "numericstepper", prompt: toLocale("finStackMobileExt::alarmPollRate"), minVal: 3, defVal: pollRate},
    {name: "notifications", editorType: "checkbox", label: toLocale("finStackMobileExt::disableAlarmNotif"), defVal: disableNotifications},
    {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
    {name: "commitButton", editorType: "button", label: toLocale("finStackExt::coreApply"), controlBar: true}
  ]

  {
    "dis": toLocale("finStackMobileExt::alarmSettingsTitle"),
    "name": "finAlarmSettingsForm",
    "body": body.toJSON,
    "cancelButton": "\$cancelButton",
    "commitButton": "\$commitButton",
    "commitAction": "", //"finAlarmSettingsForm({poll: \$poll, disb: \$disb})",
    "completeAction": "app.UpdateAlarmSettings(\$pollRate < 3 ? 3 : \$pollRate, \$notifications)",
    "finForm": marker()
  }.toGrid.addMeta({formExecute: marker()})
  // end
  // else do
  //   stuff: {}

  //   if(data->poll == 0) stuff = stuff.set("alarmPollRate", removeMarker())
  //   else stuff = stuff.set("alarmPollRate", data->poll * 1s)

  //   if(data->disb) stuff = stuff.set("disableAlarmNotification", marker())
  //   else stuff = stuff.set("disableAlarmNotification", removeMarker())

  //   if(readCount(finAlarm) == 0) diff(null, stuff.set("finAlarm", marker()), {add}).commit
  //   else read(finAlarm).diff(stuff).commit
  // end
end


def ​

func:finApplyTagBundle ​

finApplyTagBundle(tagBundles, targetFilter, customTags: [], unapply: false) ​

Applies the passed tagBundles addTags and removeTags properties to the targetFilter that fits a tagBundle's allowFilter.

tagBundles - A single tagBundle record or a list of tagBundles records.

targetFilter - A filter in the format of a string or a list of records. This will be the target of each tagBundle.


meta ​

constructfinApplyTagBundle(read(tagBundle), read(floor))
deffunc:finApplyTagBundle
isfunc
liblib:finStackMobile
namefinApplyTagBundle
overridable✓
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(tagBundles, targetFilter, customTags: [], unapply:false) => do
  targets: targetFilter
  action: ""
  transientTags: ["writeLevel"]  //need a better way to find these

  checkSharedTags: (bundleDict, curBundleDis, tagList) =>
  do
    bundleDict.names.each bundleType =>
    do
      if (bundleDict[bundleType] != null)
      do
        bundleDict[bundleType].each bundle =>
        do
          if (bundle != curBundleDis)
          do
            bundleRec: read(tagBundle and dis == bundle, false)

            if (bundleRec != null and bundleRec["addTags"] != null)
            do
              eval("{"+bundleRec->addTags+"}").names.each x =>
              do
                tagIndex: tagList.index(x)

                if (tagIndex != null)
                  tagList = tagList.remove(tagIndex)
              end // end eval
            end // end bundle has addTags
          end // end not same bundle
        end // end each bundle of type
      end
    end // end each bundle type loop

    return tagList
  end // end func

  //get targets
  if(not targetFilter.isList) targets = readAll(parseFilter(targetFilter))
  //else if (not targetFilter.isEmpty and targetFilter[0].isStr) targets = try targets.map(r => r.replace("@", "").parseRef).toRecList.findAll(v => not v.has("tagBundle")) catch []
  else targets = try targets.toRecList.findAll(v => not v.has("tagBundle")) catch []

  //make sure tagBundles is a list
  if(not tagBundles.isList and not tagBundles.isGrid) tagBundles = [tagBundles]

  // bundles by refs
  if(tagBundles[0].isRef) tagBundles = finFindNonDbRec(tagBundles)

  // bundles by name
  else if(tagBundles[0].isStr and (not tagBundles[0].startsWith("@") and not tagBundles[0].startsWith("p:") and not tagBundles[0].startsWith("tagBundle")))
  do
    allBundles: finFilteredFuncEval(tagBundleFunc, addTags or removeTags).addRows(readAll(tagBundle))

    tagBundles = tagBundles.map r => allBundles.find(v => v->dis == r and v.has("trackBundle"))
  end

  //loop through possible targets
  targets.each item =>
  do
    newTags: ""
    matches: false
    bundlesToTrack: []
    alarmConfigsToTrack: []
    hisConfigToTrack: []

    // for removal
    curBundlesTracked: {
      bundleList: item["bundles"],
      alarmList: item["alarmConfig"],
      hisList: item["hisConfig"],
      scheduleList: item["scheduleConfig"],
    }

    // step through each tag bundle being applied or removed
    tagBundles.each tagItem =>
    do
      customMatch: customTags.find(v => if(v->id.isStr and v->id.parseRef(false) == null)  v->id == tagItem->dis else v->id == tagItem->id)
      sharedTags: []

      if(customMatch == null) customMatch = {}

      //if bundle has no allowFilter or the target fits the bundle filter
      if(not tagItem.has("allowFilter") or tagItem->allowFilter.isEmpty or (tagItem.has("allowFilter") and ([item]).toGrid.finGridFilter(parseFilter(tagItem->allowFilter)).size != 0))
      do
        // track bundles
        if (tagItem.has("trackBundle"))
        do
          if (tagItem.has("alarmConfig")) alarmConfigsToTrack = alarmConfigsToTrack.add(tagItem->dis)
          else if (tagItem.has("hisConfig")) hisConfigToTrack = hisConfigToTrack.add(tagItem->dis)
          else bundlesToTrack = bundlesToTrack.add(tagItem->dis)
        end

        //add tags to add
        if((tagItem.has("addTags") and not tagItem->addTags.isEmpty) or (customMatch.has("addTags") and not customMatch->addTags.isEmpty))
        do
          tagsToAdd: if(customMatch["addTags"] != null) customMatch->addTags else tagItem->addTags
          matches = true

          if (tagsToAdd.isDict())
          do
            if (unapply)
            do
              temp: {}

              //tagsToAdd.names.each x => temp = temp.set(x, removeMarker())
              checkSharedTags(curBundlesTracked, tagItem.dis, tagsToAdd.names).each x => temp = temp.set(x, removeMarker())

              tagsToAdd = temp
            end

            if(not newTags.isEmpty()) newTags = newTags[0..-2] + tagsToAdd.toAxonCode[1..-1]
            else newTags = tagsToAdd.toAxonCode
          end
          else
          do
            tempTags: tagsToAdd

            if (unapply)
            do
              tempTags = tempTags.split(",").map(row =>  row.split(":")[0].trim())

              tempTags = checkSharedTags(curBundlesTracked, tagItem.dis, tempTags).map(r => r + ":removeMarker()").concat(",")

              /*tempTags = tempTags.split(",").map(row =>
              do
                tagName: row.split(":")[0].trim()

                tagName + ":removeMarker()"
              end).concat(",")*/
            end

            //replace {{asd}}
            else if(reFind(r"\{\{[^\{\}]*\}\}", tagsToAdd) != null)
            do
              tempTagList: tagsToAdd.split(",").map(row =>
              do
                dynamicTag: reFind(r"\{\{[^\{\}]*([\}\}]?|[\{\{]?)[^\{\}]*\}\}", row) //did not have () before

                if(dynamicTag != null and dynamicTag.contains("row"))
                do
                  //row = row.replace(dynamicTag, dynamicTag.replace("{{", "").replace("}}", "").replace("row", item.toAxonCode)) //all instances of row are replaced, so something like foo: {{dontThrow(row)}} will fuck up

                  //specific way
                  temp: dynamicTag.replace("{{", "").replace("}}", "").replace("row->", "")

                  if(item[temp] != null and item[temp].isStr) row = row.replace(dynamicTag, item[temp])  //foo: {{row->dis}}
                  else if(item[temp] != null) row = row.replace(dynamicTag, item[temp].toAxonCode)       //foo: {{row->area}}
                  else if(temp.contains(".") or temp.contains("(") or temp.contains(")"))                //foo: {{row->dis.startsWith("a")}}
                  do
                    rowRep: dynamicTag.replace("row", "|").split("|").size - 1

                    if(rowRep > 1)
                    do
                      temp = dynamicTag.replace("{{", "").replace("}}", "")

                      each(1..rowRep) x =>
                      do
                        match: reFind(r"[^\w]+row[^\w]*|^row[^\w]*", temp)
                        if(match != null) temp = temp.replace(match, match.replace("row", item.toAxonCode))
                      end
                    end
                    else temp = eval(dynamicTag.replace("{{", "").replace("}}", "").replace("row", "readById("+item->id.toAxonCode+")"))

                    if(temp.isStr) row.replace(dynamicTag, temp)
                    else  row.replace(dynamicTag, temp.toAxonCode)
                  end
                end
                else if(dynamicTag != null) row.replace(dynamicTag, dynamicTag.replace("{{", "").replace("}}", "")) //foo: {{1 + 2}}
                else row
              end)

              tempTags = tempTagList.concat(",")
            end

            if(not newTags.isEmpty()) newTags = newTags[0..-2] + "," + tempTags + "}"
            else newTags = "{" + tempTags + "}"
          end
        end //end add tags

        //add tags to remove
        if (tagItem.has("removeTags") and not tagItem->removeTags.isEmpty or (customMatch.has("removeTags") and not customMatch->removeTags.isEmpty) and not unapply)
        do
          tagsToRemove: if(customMatch["removeTags"] != null) customMatch->removeTags else tagItem->removeTags
          matches = true

          if(tagsToRemove.isDict())
          do
            if(not newTags.isEmpty()) newTags = newTags[0..-2] + tagsToRemove.toAxonCode.replace(":removeMarker()", "").replace(" ", "").replace("{", "{-").replace(",", ",-")[1..-1]
            else newTags = tagsToRemove.toAxonCode.replace(":removeMarker()", "").replace(" ", "").replace("{", "{-").replace(",", ",-")
          end
          else
          do
            if(not newTags.isEmpty()) newTags = newTags[0..-2] + "," +tagsToRemove + "}"
            else newTags = "{"+tagsToRemove+"}"
          end //end if newTags is empty or not
        end //end remove tags
      end //end if not filtered out
    end //end bundle loop

    //apply tags
    if(matches)
    do
      writeTransiently:[]
      writePersitently:[]
      newTags = newTags[1..-2].split(",")

      // track normal bundles
      if (not bundlesToTrack.isEmpty())
      do
        bundlesTag: "bundles: "

        if (unapply)
        do
          curBConfig: try item->bundles.findAll(v => not bundlesToTrack.contains(v)) catch []

          if (item.has("bundles"))
          do
            if (curBConfig.isEmpty) bundlesTag = "-bundles"
            else bundlesTag = bundlesTag + curBConfig.toAxonCode
          end
          else
            bundlesTag = "-bundles"
        end
        else
        do
          if (item.has("bundles")) bundlesTag = bundlesTag + item->bundles.addAll(bundlesToTrack).unique.toAxonCode
          else bundlesTag = bundlesTag + bundlesToTrack.toAxonCode
        end

        writePersitently = writePersitently.add(bundlesTag)
      end

      // track alarm config bundles
      if (not alarmConfigsToTrack.isEmpty())
      do
        alarmConfigTag: "alarmConfig: "

        if (unapply)
        do
          curAConfig: try item->alarmConfig.findAll(v => not alarmConfigsToTrack.contains(v)) catch []

          if (item.has("alarmConfig"))
          do
            if (curAConfig.isEmpty) alarmConfigTag = "-alarmConfig"
            else alarmConfigTag = alarmConfigTag + curAConfig.toAxonCode
          end
          else
            alarmConfigTag = "-alarmConfig"
        end
        else
        do
          if (item.has("alarmConfig")) alarmConfigTag = alarmConfigTag + item->alarmConfig.addAll(alarmConfigsToTrack).unique.toAxonCode
          else alarmConfigTag = alarmConfigTag + alarmConfigsToTrack.toAxonCode
        end

        writePersitently = writePersitently.add(alarmConfigTag)
      end

      // track his config bundles
      if (not hisConfigToTrack.isEmpty())
      do
        hisConfigTag: "hisConfig: "

        if (unapply)
        do
          curHConfig: try item->hisConfig.findAll(v => not hisConfigToTrack.contains(v)) catch []

          if (item.has("hisConfig"))
          do
            if (curHConfig.isEmpty) hisConfigTag = "-hisConfig"
            else hisConfigTag = hisConfigTag + curHConfig.toAxonCode
          end
          else
            hisConfigTag = "-hisConfig"
        end
        else
        do
          if (item.has("hisConfig")) hisConfigTag = hisConfigTag + item->hisConfig.addAll(hisConfigToTrack).unique.toAxonCode
          else hisConfigTag = hisConfigTag + hisConfigToTrack.toAxonCode
        end

        writePersitently = writePersitently.add(hisConfigTag)
      end

      // track schedule config bundles
      // TODO

      newTags.each x => if (transientTags.find(v => x.startsWith(v) or x.startsWith("-"+v)) != null) writeTransiently = writeTransiently.add(x) else writePersitently = writePersitently.add(x)

      if(not writeTransiently.isEmpty) eval("readById("+item->id.toAxonCode+").diff({"+writeTransiently.concat(",").replace("\$", "\\\$")+"}, {transient}).commit")
      if(not writePersitently.isEmpty) eval("readById("+item->id.toAxonCode+").diff({"+writePersitently.concat(",").replace("\$", "\\\$")+"}).commit")
    end
  end //end target loop
end //end func


def ​

func:finBackupRecordForm ​

finBackupRecordForm(selected: null) ​

Axon function


meta ​

deffunc:finBackupRecordForm
isfunc
liblib:finStackMobile
namefinBackupRecordForm
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(selected: null) => do
  if(selected == null) selected = "site"

  body: [
  {name: "filter", editorType: "filter", prompt: toLocale("finStackExt::finFilter"), defVal: selected},
  {name: "chkbx", editorType: "checkbox", label: toLocale("finStackExt::selectAll"), defVal: true},
  {name: "list", editorType: "list", listType: "checkbox", labelField: "dis", selectedValueTags: "id", defValTagName: "selected", height: 200,
    dataProvider: "try readAll(parseFilter(\$filter)).map(x=> x.set(\"selected\",\$chkbx).set(\"dis\",x.dis)).sort(\"dis\") catch []"},
  {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
  {name: "commitButton", editorType: "button", label: toLocale("finStackMobileExt::coreBackup"), controlBar: true}
  ]

  {"dis":toLocale("finStackMobileExt::buRecs"),
  "name":"finBackupRecordForm",
  "body":body.toJSON,
  "cancelButton": "\$cancelButton",
  "commitButton": "\$commitButton",
  "commitAction": "",
  "completeAction": [
    "console.log('\$list');",
    "var promise = finstack.eval('finBackupRecord(\$list, {everything:true})');",
    "promise.then(function(event){",
      "var fileRec = event.result.toObj()[0];",
      "finstack.eval('readById('+fileRec.id+').diff({dis:\"'+fileRec.dis+'.zip\"}).commit');",
      "window.open((finstack.pathPrefix || '')+'/finGetFile/"+context()->projName+"?fileRef='+fileRec.id, '_parent');",
    "});"].concat(" "),
  "finForm": marker()
  }.toGrid.addMeta({formExecute: marker()})
end


def ​

func:finBackupUploadForm ​

finBackupUploadForm(selected: null) ​

Axon function


meta ​

deffunc:finBackupUploadForm
isfunc
liblib:finStackMobile
namefinBackupUploadForm
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(selected: null) => do
  compAct: ""
  if(selected != null) do
    if(selected == "program") compAct = "setTimeout(function(){ window.app.ObtainMenu(null, '{{targetRef}}','bline', "+ blineMenuSettings(null, false).toAxonCode +"); }, 2000);"
    else if(selected == "graphics") compAct = "setTimeout(function(){ window.app.ObtainMenu(null, '{{targetRef}}','graphicsBuilder', "+ graphicsMenuSettings(false).toAxonCode +"); }, 2000);"
    else if(selected == "file") compAct = "setTimeout(function(){ window.app.ObtainMenu(null, null,'folio',"+ finFolioSettings("folioFileMenu").toAxonCode +"); }, 2000);"
    else if(selected == "job") compAct = "setTimeout(function(){ window.app.ObtainMenu(null, null,'job', {header:'Jobs', funcCall:'finJobMenu2()', display:'dis'}); }, 2000);"
    else if(selected == "schedule") compAct = "setTimeout(function(){ window.app.NavigateToApp(window.app.APP_NAMES.SCHEDULES, window.app.get('currentId')); }, 2000);"
  end

  body: [
  {name: "file", editorType: "file", prompt: toLocale("finStackMobileExt::restoreZIPFile")},
  {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
  {name: "commitButton", editorType: "button", label: toLocale("finStackMobileExt::coreRestore"), controlBar: true}
  ]

  {"dis":toLocale("finStackMobileExt::coreRestore"),
  "name":"finBackupUploadForm",
  "body":body.toJSON,
  "cancelButton": "\$cancelButton",
  "commitButton": "\$commitButton",
  "commitAction": "finRestoreRecord(\$file)",
  "completeAction": compAct,
  "finForm": marker()
  }.toGrid.addMeta({formExecute: marker()})
end


def ​

func:finBlocks ​

finBlocks() ​

This function uses the blocks() function to gather all blocks and then adds additional information too each block specific to FIN Stack.

Returns ​

Grid: A grid of all bLine blocks and information about each blocks such as what they can be interchanged with and what category they belong to.

Examples ​

Get all blocks.

finBlocks()

meta ​

constructfinBlocks()
deffunc:finBlocks
isfunc
liblib:finStackMobile
namefinBlocks

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

() => do
  grid: blocks()
  changesDict: {
    "abs":                {category: toLocale("finStackMobileExt::finMath"), interchangeableWith: ""},
    "aboveBy":            {category: toLocale("finStackMobileExt::finMath"), interchangeableWith: "belowBy within"},
    "add":                {category: toLocale("finStackMobileExt::finMath"), interchangeableWith: "mult sub div"},
    "all":                {category: toLocale("finStackMobileExt::logical"), interchangeableWith: "any"},
    "and":                {category: toLocale("finStackMobileExt::logical"), interchangeableWith: "or xor"},
    "any":                {category: toLocale("finStackMobileExt::logical"), interchangeableWith: "all"},
    "avg":                {category: toLocale("finStackMobileExt::finMath"), interchangeableWith: ""},
    "belowBy":            {category: toLocale("finStackMobileExt::finMath"), interchangeableWith: "aboveBy within"},
    "boolLatch":          {category: toLocale("finStackMobileExt::block.programming.language"), interchangeableWith: ""},
    "cmpEq":              {category: toLocale("finStackMobileExt::logical"), interchangeableWith: "cmpGt cmpGtEq cmpLt cmpLtEq cmpNotEq"},
    "cmpGt":              {category: toLocale("finStackMobileExt::logical"), interchangeableWith: "cmpEq cmpGtEq cmpLt cmpLtEq cmpNotEq"},
    "cmpGtEq":            {category: toLocale("finStackMobileExt::logical"), interchangeableWith: "cmpEq cmpGt cmpLt cmpLtEq cmpNotEq"},
    "cmpLt":              {category: toLocale("finStackMobileExt::logical"), interchangeableWith: "cmpEq cmpGt cmpGtEq cmpLtEq cmpNotEq"},
    "cmpLtEq":            {category: toLocale("finStackMobileExt::logical"), interchangeableWith: "cmpEq cmpGt cmpGtEq cmpLt cmpNotEq"},
    "cmpNotEq":           {category: toLocale("finStackMobileExt::logical"), interchangeableWith: "cmpEq cmpGt cmpGtEq cmpLt cmpLtEq"},
    "comment":            {category: toLocale("finStackMobileExt::block.programming.language"), interchangeableWith: ""},
    "condDelay":          {category: toLocale("finStackMobileExt::commands"), interchangeableWith: ""},
    "count":              {category: toLocale("finStackMobileExt::expression"), interchangeableWith: ""},
    "date":               {category: toLocale("finStackMobileExt::debugMenuTime").decapitalize, interchangeableWith: ""},
    "dateTimeAdd":        {category: toLocale("finStackMobileExt::debugMenuTime").decapitalize, interchangeableWith: ""},
    "dateTimeSub":        {category: toLocale("finStackMobileExt::debugMenuTime").decapitalize, interchangeableWith: ""},
    "dateToNumber":       {category: toLocale("finStackMobileExt::debugMenuTime").decapitalize, interchangeableWith: ""},
    "dateToString":       {category: toLocale("finStackMobileExt::debugMenuTime").decapitalize, interchangeableWith: ""},
    "delayedOutput":      {category: toLocale("finStackMobileExt::block.programming.language"), interchangeableWith: ""},
    "dictGet":            {category: toLocale("finStackMobileExt::block.programming.language"), interchangeableWith: ""},
    "div":                {category: toLocale("finStackMobileExt::finMath"), interchangeableWith: "mult add sub"},
    "dtToDtAdd":          {category: toLocale("finStackMobileExt::debugMenuTime").decapitalize, interchangeableWith: ""},
    "dtToDtSub":          {category: toLocale("finStackMobileExt::debugMenuTime").decapitalize, interchangeableWith: ""},
    "email":              {category: toLocale("finStackMobileExt::commands"), interchangeableWith: ""},
    "exprStmt":           {category: toLocale("finStackMobileExt::block.programming.language"), interchangeableWith: ""},
    "gridSelectCol":      {category: toLocale("finStackMobileExt::expression"), interchangeableWith: ""},
    "gridSize":           {category: toLocale("finStackMobileExt::expression"), interchangeableWith: ""},
    "if":                 {category: toLocale("finStackMobileExt::controlFlow"), interchangeableWith: ""},
    "inRange":            {category: toLocale("finStackMobileExt::logical"), interchangeableWith: ""},
    "isEven":             {category: toLocale("finStackMobileExt::finMath"), interchangeableWith: ""},
    "isOdd":              {category: toLocale("finStackMobileExt::finMath"), interchangeableWith: ""},
    "isType":             {category: toLocale("finStackMobileExt::logical"), interchangeableWith: ""},
    "jobRun":             {category: toLocale("finStackMobileExt::block.programming.language"), interchangeableWith: ""},
    "leadLag":            {category: toLocale("finStackMobileExt::expression"), interchangeableWith: ""},
    "leadLagStageSelect": {category: toLocale("finStackMobileExt::expression"), interchangeableWith: ""},
    "limit":              {category: toLocale("finStackMobileExt::finMath"), interchangeableWith: ""},
    "max":                {category: toLocale("finStackMobileExt::finMath"), interchangeableWith: "min"},
    "min":                {category: toLocale("finStackMobileExt::finMath"), interchangeableWith: "max"},
    "modulo":             {category: toLocale("finStackMobileExt::finMath"), interchangeableWith: ""},
    "mult":               {category: toLocale("finStackMobileExt::finMath"), interchangeableWith: "add sub div"},
    "neg":                {category: toLocale("finStackMobileExt::finMath"), interchangeableWith: ""},
    "not":                {category: toLocale("finStackMobileExt::logical"), interchangeableWith: ""},
    "now":                {category: toLocale("finStackMobileExt::debugMenuTime").decapitalize, interchangeableWith: ""},
    "or":                 {category: toLocale("finStackMobileExt::logical"), interchangeableWith: "and xor"},
    "pid":                {category: toLocale("finStackMobileExt::expression"), interchangeableWith: ""},
    "pow":                {category: toLocale("finStackMobileExt::finMath"), interchangeableWith: ""},
    "random":             {category: toLocale("finStackMobileExt::finMath"), interchangeableWith: ""},
    "reset":              {category: toLocale("finStackMobileExt::finMath"), interchangeableWith: ""},
    "setDelay":           {category: toLocale("finStackMobileExt::commands"), interchangeableWith: "set"},
    "setExternal":        {category: toLocale("finStackMobileExt::commands"), interchangeableWith: ""},
    "sineWave":           {category: toLocale("finStackMobileExt::finMath"), interchangeableWith: ""},
    "siteDateTime":       {category: toLocale("finStackMobileExt::debugMenuTime").decapitalize, interchangeableWith: ""},
    "sqrt":               {category: toLocale("finStackMobileExt::finMath"), interchangeableWith: ""},
    "staging":            {category: toLocale("finStackMobileExt::block.programming.language"), interchangeableWith: ""},
    "strCapitalize":      {category: toLocale("finStackMobileExt::strings"), interchangeableWith: ""},
    "strConcat":          {category: toLocale("finStackMobileExt::strings"), interchangeableWith: ""},
    "strContains":        {category: toLocale("finStackMobileExt::strings"), interchangeableWith: ""},
    "strDecapitalize":    {category: toLocale("finStackMobileExt::strings"), interchangeableWith: ""},
    "strEndsWith":        {category: toLocale("finStackMobileExt::strings"), interchangeableWith: ""},
    "strFormat":          {category: toLocale("finStackMobileExt::strings"), interchangeableWith: ""},
    "strLower":           {category: toLocale("finStackMobileExt::strings"), interchangeableWith: ""},
    "strMacro":           {category: toLocale("finStackMobileExt::strings"), interchangeableWith: ""},
    "strReplace":         {category: toLocale("finStackMobileExt::strings"), interchangeableWith: ""},
    "strSize":            {category: toLocale("finStackMobileExt::strings"), interchangeableWith: ""},
    "strStartsWith":      {category: toLocale("finStackMobileExt::strings"), interchangeableWith: ""},
    "strUpper":           {category: toLocale("finStackMobileExt::strings"), interchangeableWith: ""},
    "sub":                {category: toLocale("finStackMobileExt::finMath"), interchangeableWith: "add mult div"},
    "threshold":          {category: toLocale("finStackMobileExt::finMath"), interchangeableWith: ""},
    "time":               {category: toLocale("finStackMobileExt::debugMenuTime").decapitalize, interchangeableWith: ""},
    "timeToMinutes":      {category: toLocale("finStackMobileExt::debugMenuTime").decapitalize, interchangeableWith: ""},
    "timeToTimeAdd":      {category: toLocale("finStackMobileExt::debugMenuTime").decapitalize, interchangeableWith: ""},
    "timeToTimeSub":      {category: toLocale("finStackMobileExt::debugMenuTime").decapitalize, interchangeableWith: ""},
    "varCapture":         {category: toLocale("finStackMobileExt::block.programming.language"), interchangeableWith: ""},
    "wait":               {category: toLocale("finStackMobileExt::commands"), interchangeableWith: ""},
    "weatherConditions":  {category: toLocale("finStackMobileExt::rightMenuWeather").decapitalize, interchangeableWith: ""},
    "weatherInfo":        {category: toLocale("finStackMobileExt::rightMenuWeather").decapitalize, interchangeableWith: ""},
    "weatherSunrise":     {category: toLocale("finStackMobileExt::rightMenuWeather").decapitalize, interchangeableWith: ""},
    "weatherSunset":      {category: toLocale("finStackMobileExt::rightMenuWeather").decapitalize, interchangeableWith: ""},
    "within":             {category: toLocale("finStackMobileExt::finMath"), interchangeableWith: "aboveBy belowBy"},
    "xor":                {category: toLocale("finStackMobileExt::logical"), interchangeableWith: "and or"}
  }

  grid2: grid.map(r =>
  do
    changes: changesDict[r->name]

    if (changes == null)
      changes = {}

    if (r["doc"] != null and not r->doc.isEmpty and toLocale("finStackMobileExt::block.doc."+r->name) != "finStackMobileExt::block.doc."+r->name)
      changes = changes.set("doc", toLocale("finStackMobileExt::block.doc."+r->name))

    if (r["props"] != null and not r->props.isEmpty)
    do
      blockProps: r->props.ioReadZinc.map(pr =>
      do
        key: "finStackMobileExt::block.props."+pr->name

        // key exists
        if (toLocale(key) != key)
          return pr.merge({doc: toLocale(key)})

        // try more than 1 doc key format
        extendedKey: ""

        if (pr["doc"] != null and not pr->doc.isEmpty())
          extendedKey = r->name + r->doc.toTagName

        if (extendedKey.size > 25)
          extendedKey = extendedKey[0..24]

        key = key.replace(r->name, extendedKey)

        // new key exists
        if (not extendedKey.isEmpty() and toLocale(key) != key)
          return pr.merge({doc: toLocale(key)})

        // no key exists, keep original
        return pr
      end).ioWriteZinc("")

      changes = changes.set("props", blockProps)
    end

    r.merge(changes)
  end)

  grid2
end


def ​

func:finBlocksJavaScript ​

finBlocksJavaScript() ​

Axon function


meta ​

deffunc:finBlocksJavaScript
isfunc
liblib:finStackMobile
namefinBlocksJavaScript
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

() => do
  ioReadTrio(`fan://finStackMobileExt/libs/finBlocksJavaScript.trio`)
end


def ​

func:finBlocksPpcl ​

finBlocksPpcl() ​

Axon function


meta ​

deffunc:finBlocksPpcl
isfunc
liblib:finStackMobile
namefinBlocksPpcl
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

() => do
  ioReadTrio(`fan://finStackMobileExt/libs/finBlocksPpcl.trio`)
end


def ​

func:finBreadcrumbs ​

finBreadcrumbs(treeType: "equip", targetRef: null, maxLevels: null) ​

Axon function


meta ​

deffunc:finBreadcrumbs
isfunc
liblib:finStackMobile
namefinBreadcrumbs
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(treeType: "equip", targetRef: null, maxLevels: null) => do
  treeType = treeType.replace("treeName:", "").replace("readAll(", "").replace(")", "")

  curLevel: if(targetRef != null) readById(targetRef, false) else null
  userDict: finGetCurrentUser()
  treeTypeList: finNavTreeTypes().map(r => r.set("dis", r->dis.toTagName))
  breadList: []
  curTree: treeTypeList.find(v => v->dis.contains(treeType) or v->dis == treeType)

  if(curLevel != null and curLevel.has("point") and treeType == "equip" or treeType == "equipTree") do
    targetRef = curLevel->equipRef
    curLevel = readById(targetRef, false)
  end

  metaDict: {
    selectedTree: if(curTree != null) curTree->finNavList else treeType,
    allowedTrees: if(userDict == null or not userDict.has("headerTreeTypes")) [] else userDict->headerTreeType.split(","),
    levelsHidden: 0
  }

  if(maxLevels != null and maxLevels < 2) maxLevels = 2
  if(userDict->username == "su") userDict = null

  if(treeType == "equip" or treeType == "equipTree" or treeType == "alarm" or treeType == "alarmTargets" or treeType == "noteTargets" or treeType == "note") do
    curLevelType: if(curLevel != null) finNavMetaWhoAmI(curLevel) else ""
    navTree: read(navMeta)->equipPath.split("/")

    if(curLevelType == "") return breadList

    breadList = breadList.addAll(finClimbNavTree(curLevelType, targetRef))

    //if(treeType == "alarm")
  //end else if(treeType == "alarm") do
    //alarmList: navFilter("alarmTarget", null, null).alarms(today).findAll(v => v->targetRef == targetRef)
    //"do alarm stuff"
  end else do
    curPath: if(curLevel != null and curLevel.has("folderPath")) curLevel->folderPath.split("/") else null

    if(curPath != null) breadList = breadList.addAll(curPath.map((r, i) => {dis: r, folderPath: if(i > 0) curPath[0..(i-1)].concat("/") else ""})) //curPath.replace(r, "").replace("//", "")

    breadList = breadList.add(curLevel)
  end

  if(maxLevels != null and (breadList.size > maxLevels)) do
    overBy: (breadList.size) - maxLevels

    (1..overBy).each x => breadList = breadList.remove(1)

    metaDict = metaDict.merge({levelsHidden: overBy})
  end

  return breadList.insert(0, metaDict)
end


def ​

func:finBuilderContextMenuItems ​

finBuilderContextMenuItems() ​

Axon function


meta ​

deffunc:finBuilderContextMenuItems
finBuilderMenu✓
isfunc
liblib:finStackMobile
namefinBuilderContextMenuItems
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

() => do
  m: [
    {
      dis: toLocale("finStackMobileExt::alarmShowHide"),
      name: "fin_menu_hideshow",
      menuOn: "component",
      icon: "",
      folderPath: "",
      body: "facade.sendNotification('executeExternal',{builderAction:'toggleVisibility'})"
    },

    {
      dis: toLocale("finStackMobileExt::gbEditProps"),
      name: "fin_menu_editProperties",
      menuOn: "component",
      icon: "icon-tags",
      folderPath: "",
      body: "facade.sendNotification('executeExternal',{builderAction:'editProperties'})"
    },
    {
      dis: toLocale("finStackMobileExt::gbStatusIndicator"),
      name: "fin_menu_statusIndicator",
      menuOn: "statusIndicator",
      icon: "icon-tags",
      folderPath: "",
      body: "facade.sendNotification('executeExternal',{builderAction:'statusIndicator'})"
    },
    // align
    {
      dis: toLocale("finStackMobileExt::gbAlignLeft"),
      name: "fin_menu_align_left",
      menuOn: "component",
      icon: "sm-align-left",
      folderPath: toLocale("finStackMobileExt::gbAlignDistribute") + "/" + toLocale("finStackMobileExt::gbAlign") + "/",
      body: "facade.sendNotification('executeExternal',{builderAction:'align',params:'left'})"
    },
    {
      dis: toLocale("finStackMobileExt::gbAlignRight"),
      name: "fin_menu_align_right",
      menuOn: "component",
      icon: "sm-align-right",
      folderPath: toLocale("finStackMobileExt::gbAlignDistribute") + "/" + toLocale("finStackMobileExt::gbAlign") + "/",
      body: "facade.sendNotification('executeExternal',{builderAction:'align',params:'right'})"
    },
    {
      dis: toLocale("finStackMobileExt::gbAlignMiddle"),
      name: "fin_menu_align_middle",
      menuOn: "component",
      icon: "sm-align-middle",
      folderPath: toLocale("finStackMobileExt::gbAlignDistribute") + "/" + toLocale("finStackMobileExt::gbAlign") + "/",
      body: "facade.sendNotification('executeExternal',{builderAction:'align',params:'hMiddle'})"
    },
    {
      dis: toLocale("finStackMobileExt::gbAlignTop"),
      name: "fin_menu_align_top",
      menuOn: "component",
      icon: "sm-align-top",
      folderPath: toLocale("finStackMobileExt::gbAlignDistribute") + "/" + toLocale("finStackMobileExt::gbAlign") + "/",
      body: "facade.sendNotification('executeExternal',{builderAction:'align',params:'top'})"
    },
    {
      dis: toLocale("finStackMobileExt::gbAlignBottom"),
      name: "fin_menu_align_bottom",
      menuOn: "component",
      icon: "sm-align-bottom",
      folderPath: toLocale("finStackMobileExt::gbAlignDistribute") + "/" + toLocale("finStackMobileExt::gbAlign") + "/",
      body: "facade.sendNotification('executeExternal',{builderAction:'align',params:'bottom'})"
    },
    {
      dis: toLocale("finStackMobileExt::gbAlignCenter"),
      name: "fin_menu_align_center",
      menuOn: "component",
      icon: "sm-align-center",
      folderPath: toLocale("finStackMobileExt::gbAlignDistribute") + "/" + toLocale("finStackMobileExt::gbAlign") + "/",
      body: "facade.sendNotification('executeExternal',{builderAction:'align',params:'vCenter'})"
    },

    //distribute
    {
      dis: toLocale("finStackMobileExt::gbDistributeLeft"),
      name: "fin_menu_distribute_left",
      menuOn: "component",
      icon: "sm-align-left",
      folderPath: toLocale("finStackMobileExt::gbAlignDistribute") + "/" + toLocale("finStackMobileExt::gbDistribute") + "/",
      body: "facade.sendNotification('executeExternal',{builderAction:'distribute',params:'left'})"
    },
    {
      dis: toLocale("finStackMobileExt::gbDistributeRight"),
      name: "fin_menu_distribute_right",
      menuOn: "component",
      icon: "sm-align-right",
      folderPath: toLocale("finStackMobileExt::gbAlignDistribute") + "/" + toLocale("finStackMobileExt::gbDistribute") + "/",
      body: "facade.sendNotification('executeExternal',{builderAction:'distribute',params:'right'})"
    },
    {
      dis: toLocale("finStackMobileExt::gbDistributeMiddle"),
      name: "fin_menu_distribute_middle",
      menuOn: "component",
      icon: "sm-align-middle",
      folderPath: toLocale("finStackMobileExt::gbAlignDistribute") + "/" + toLocale("finStackMobileExt::gbDistribute") + "/",
      body: "facade.sendNotification('executeExternal',{builderAction:'distribute',params:'hMiddle'})"
    },
    {
      dis: toLocale("finStackMobileExt::gbDistributeTop"),
      name: "fin_menu_distribute_top",
      menuOn: "component",
      icon: "sm-align-top",
      folderPath: toLocale("finStackMobileExt::gbAlignDistribute") + "/" + toLocale("finStackMobileExt::gbDistribute") + "/",
      body: "facade.sendNotification('executeExternal',{builderAction:'distribute',params:'top'})"
    },
    {
      dis: toLocale("finStackMobileExt::gbDistributeBottom"),
      name: "fin_menu_distribute_bottom",
      menuOn: "component",
      icon: "sm-align-bottom",
      folderPath: toLocale("finStackMobileExt::gbAlignDistribute") + "/" + toLocale("finStackMobileExt::gbDistribute") + "/",
      body: "facade.sendNotification('executeExternal',{builderAction:'distribute',params:'bottom'})"
    },
    {
      dis: toLocale("finStackMobileExt::gbDistributeCenter"),
      name: "fin_menu_distribute_center",
      menuOn: "component",
      icon: "sm-align-center",
      folderPath: toLocale("finStackMobileExt::gbAlignDistribute") + "/" + toLocale("finStackMobileExt::gbDistribute") + "/",
      body: "facade.sendNotification('executeExternal',{builderAction:'distribute',params:'vCenter'})"
    },

    //mass edit
    {
      dis: toLocale("finStackMobileExt::gbCopyProps"),
      name: "fin_menu_massedit_copy",
      menuOn: "component",
      icon: "icon-copy",
      folderPath: toLocale("finStackMobileExt::coreTools") + "/" + toLocale("finStackMobileExt::gbMassEdit") + "/",
      body: "facade.sendNotification('executeExternal',{builderAction:'properties:',params:'copy'})"
    },
    {
      dis: toLocale("finStackMobileExt::gbPasteProps"),
      name: "fin_menu_massedit_paste",
      menuOn: "component",
      icon: "icon-duplicate",
      folderPath: toLocale("finStackMobileExt::coreTools") + "/" + toLocale("finStackMobileExt::gbMassEdit") + "/",
      body: "facade.sendNotification('executeExternal',{builderAction:'properties:',params:'paste'})"
    },
    {
      dis: toLocale("finStackMobileExt::gbEditProps"),
      name: "fin_menu_massedit_edit",
      menuOn: "component",
      icon: "icon-pencil",
      folderPath: toLocale("finStackMobileExt::coreTools") + "/" + toLocale("finStackMobileExt::gbMassEdit") + "/",
      body: "facade.sendNotification('executeExternal',{builderAction:'properties:',params:'edit'})"
    },

    //apply batch tags
    {
      dis: toLocale("finStackExt::gbApplyBatchTags"),
      name: "fin_menu_applybatchtags",
      menuOn: "component",
      icon: "icon-tags",
      folderPath: toLocale("finStackMobileExt::coreTools") + "/",
      body: "facade.sendNotification('executeExternal',{builderAction:'form:applyBatchTags'})"
    },

    {
      dis: toLocale("finStackMobileExt::gbFillOpacity"),
      name: "fin_menu_Opacity",
      menuOn: "elementTagName==\"svg\"",
      icon: "icon-tags",
      folderPath: toLocale("finStackMobileExt::coreTools") + "/",
      body: "facade.sendNotification('executeExternal',{builderAction:'svgOpacity'})"
    },
    {
      dis: toLocale("finStackMobileExt::gbCreateQueryProg"),
      name: "fin_menu_create_program",
      menuOn: "component",
      icon: "",
      folderPath: toLocale("finStackMobileExt::coreTools") + "/",
      body: "facade.sendNotification('executeExternal',{builderAction:'addProgram'})"
    },

    //{dis:"Configure Chart", name: "fin_config_chart", menuOn: "dashboardChart", icon: "", folderPath: toLocale("finStackMobileExt::coreTools")+"/", body: "facade.sendNotification('executeExternal',{builderAction:'configureChart'})"},
    //{dis:"Add Chart", name: "fin_config_chart2", menuOn: "button and divId", icon: "", folderPath: toLocale("finStackMobileExt::trendsChart") + "/", body: "facade.sendNotification('executeExternal',{builderAction:'createChart',params:this.model})"},
    {
      dis: toLocale("finStackMobileExt::addEditChart"),
      name: "fin_config_chart3",
      menuOn: "button and divId",
      icon: "",
      folderPath: toLocale("finStackMobileExt::trendsChart") + "/",
      body: "facade.sendNotification('executeExternal',{builderAction:'configureChart',params:this.model})"
    },
    {
      dis: toLocale("finStackMobileExt::removeChart"),
      name: "fin_config_chart4",
      menuOn: "button and divId",
      icon: "",
      folderPath: toLocale("finStackMobileExt::trendsChart") + "/",
      body: "facade.sendNotification('executeExternal',{builderAction:'removeChart',params:this.model})"
    },

    {
      dis: toLocale("finStackMobileExt::removeDuplicatePrograms"),
      name: "fin_menu_remove_dup_programs",
      menuOn: "component",
      icon: "",
      folderPath: toLocale("finStackMobileExt::coreTools") + "/",
      body: "facade.sendNotification('executeExternal',{builderAction:'removeDupPrograms'})"
    },
  ]
  if (exts().find(x => x-> name == "siemensGraphicResources") == null)
    m = m.addAll([ //stuff that siemens shouldn't see
      {
        dis: toLocale("finStackMobileExt::toggleInteractivity"),
        name: "fin_menu_sup_12",
        menuOn: "component",
        icon: "",
        folderPath: toLocale("finStackMobileExt::coreTools") + "/",
        body: "facade.sendNotification('executeExternal',{builderAction:'magicFuncs',params:'toggleSupInteractivity'})"
      },
      {
        dis: toLocale("finStackMobileExt::addHyperlinks"),
        name: "fin_menu_add_hyperlinks",
        menuOn: "component",
        icon: "",
        folderPath: toLocale("finStackMobileExt::coreTools") + "/",
        body: "facade.sendNotification('executeExternal',{ builderAction:'menu:finGraphicAddHyperlinkFormStandard' })"
      },
      //resources
      {
        dis: toLocale("finStackMobileExt::addRemote"),
        name: "fin_menu_resource_addremote",
        menuOn: "component",
        icon: "",
        folderPath: toLocale("finStackMobileExt::coreTools") + "/" + toLocale("finStackMobileExt::resources") + "/",
        body: "facade.sendNotification('executeExternal',{builderAction:'resources:',params:'addRemote'})"
      },
      {
        dis: toLocale("finStackExt::weatherMenuAdd"),
        name: "fin_menu_resource_add",
        menuOn: "component",
        icon: "",
        folderPath: toLocale("finStackMobileExt::coreTools") + "/" + toLocale("finStackMobileExt::resources") + "/",
        body: "facade.sendNotification('executeExternal',{builderAction:'resources:',params:'addFromServer'})"
      },
      {
        dis: toLocale("finStackExt::delete"),
        name: "fin_menu_resource_delete",
        menuOn: "component",
        icon: "",
        folderPath: toLocale("finStackMobileExt::coreTools") + "/" + toLocale("finStackMobileExt::resources") + "/",
        body: "facade.sendNotification('executeExternal',{builderAction:'resources:',params:'delete'})"
      },
      {
        dis: toLocale("finStackMobileExt::bLineNew"),
        name: "fin_menu_resource_new",
        menuOn: "component",
        icon: "",
        folderPath: toLocale("finStackMobileExt::coreTools") + "/" + toLocale("finStackMobileExt::resources") + "/",
        body: "facade.sendNotification('executeExternal',{builderAction:'resources:',params:'newResource'})"
      },
      {
        dis: toLocale("finStackExt::coreEdit"),
        name: "fin_menu_resource_edit",
        menuOn: "component",
        icon: "",
        folderPath: toLocale("finStackMobileExt::coreTools") + "/" + toLocale("finStackMobileExt::resources") + "/",
        body: "facade.sendNotification('executeExternal',{builderAction:'resources:',params:'editResource'})"
      },

      {
        dis: toLocale("finStackMobileExt::addRelatedBubbles"),
        name: "fin_menu_tool_addMBubble",
        menuOn: "component",
        icon: "",
        folderPath: toLocale("finStackMobileExt::coreTools") + "/",
        body: "facade.sendNotification('executeExternal',{builderAction:'addMagicBubbles'})"
      },

      {
        dis: toLocale("finStackMobileExt::pointCommands"),
        name: "fin_menu_tool_pointCommands",
        menuOn: "component",
        icon: "",
        folderPath: toLocale("finStackMobileExt::coreTools") + "/",
        body: "facade.sendNotification('executeExternal',{builderAction:'pointCommands'})"
      },
    ])

  m
end


def ​

func:finBuilderEquipTrash ​

finBuilderEquipTrash(recs) ​

Axon function


meta ​

deffunc:finBuilderEquipTrash
isfunc
liblib:finStackMobile
namefinBuilderEquipTrash

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function


def ​

func:finClimbNavTree ​

finClimbNavTree(curType, targetRef) ​

Axon function


meta ​

deffunc:finClimbNavTree
isfunc
liblib:finStackMobile
namefinClimbNavTree
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(curType, targetRef) => do
  navTree: read(navMeta)->equipPath.split("/")[1..-1]
  navLocation: navTree.index(curType)
  curRec: readById(targetRef, false)

  if(navLocation == 0) do
    if(not readAll(parseFilter(finNavMetaWhoAmI(curRec) + "Ref == " + targetRef.toAxonCode)).findAll(v => not v.has("point") and v.finNavMetaWhoAmI != null).isEmpty) curRec = curRec.set("isBranch", marker())

    return [curRec]
  end else do
    refList: readAllTagNames(parseFilter("id == " + targetRef.toAxonCode)).findAll(v => v->kind == "Ref" and v->name != "id" and navTree.find(x => x == v->name.replace("Ref", "")) != null)
    parent: refList.map(r => r.set("order", navTree.index(r->name.replace("Ref", "")))).sortr("order")[0]
    if(not readAll(parseFilter(finNavMetaWhoAmI(curRec) + "Ref == " + targetRef.toAxonCode)).findAll(v => not v.has("point") and v.finNavMetaWhoAmI != null).isEmpty) curRec = curRec.set("isBranch", marker())

    return finClimbNavTree(parent->name.replace("Ref", ""), readById(targetRef)[parent->name]).add(curRec)
  end
end


def ​

func:finCommonQueries ​

finCommonQueries() ​

Axon function


meta ​

deffunc:finCommonQueries
isfunc
liblib:finStackMobile
namefinCommonQueries
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

() => do
  savedFilters: try finFilteredFuncEval(savedQueryFilterFunc, filterString).addRows(readAll(savedQueryFilter)) catch [].toGrid
  commonQueries: try finFilteredFuncEval(finCommonQuery, query).addRows(readAll(finCommonQuery and not func)) catch [].toGrid

  savedFilters = savedFilters.map(r => if (r.has("folderPath")) r.merge({folderPath: toLocale("finStackMobileExt::savedFilters") + "/"+r->folderPath}) else r.merge({folderPath: toLocale("finStackMobileExt::savedFilters") + "/"}))

  if (savedFilters.isEmpty)
    return commonQueries

  return commonQueries.addRows(savedFilters)
end


def ​

func:finConstructBasicTreeItem ​

finConstructBasicTreeItem(record, treeDis, branchDis, treeInfo) ​

Axon function


meta ​

deffunc:finConstructBasicTreeItem
isfunc
liblib:finStackMobile
namefinConstructBasicTreeItem

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function


def ​

func:finContentOnFunc ​

finContentOnFunc(target: null) ​

finContentOn(Ref target: null) Finds contentOn records whose contentOn tag is compatible with the target reference. Finds finds functions with contentOn tag that is compatible with the target reference. Backend function for the O&M Manuals menu.


meta ​

deffunc:finContentOnFunc
isfunc
liblib:finStackMobile
namefinContentOnFunc
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

 (target: null) => do
   contentOn: readAll(contentOn)
   funcs(finContent and name).each x=> do
     contentOn = contentOn.addRows(eval(x->name + "()"))
   end
   if(target != null) do
     target = target.readById.toGrid
     contentOn = contentOn.findAll(x=> target.finGridFilter(x->contentOn.parseFilter).size > 0)
end
   contentOn
   //{contentOn: "", name: "", dis: "", hyperlink: ``, fileId: @, contentType: "", folderPath: ""}
 end


def ​

func:finCreateFolder ​

finCreateFolder(folderName, treeTag, parentFolderPath: null, childId: null) ​

Axon function


meta ​

deffunc:finCreateFolder
isfunc
liblib:finStackMobile
namefinCreateFolder
overridable✓
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(folderName, treeTag, parentFolderPath: null, childId: null) => do
  treeTagFilters:{
    graphics: "graphicFolder",
    programs: "programFolder",
    schedules: "scheduleFolder",
    //job: "jobFolder", //"job",
  }

  tagToAdd: treeTagFilters[treeTag]

  if(tagToAdd == null) tagToAdd = treeTag + "Folder"

  /*if(parentFolderPath != null) do
    if(not parentFolderPath.endsWith("/") and not folderName.startsWith("/"))
      folderName = parentFolderPath + "/" + folderName
    else if((not parentFolderPath.endsWith("/") and folderName.startsWith("/")) or (parentFolderPath.endsWith("/") and not foldername.startsWith("/")))
      folderName = parentFolderPath + folderName
    else
      folderName = parentFolderPath[1..-1] + folderName
  end*/

  folderName = folderName.replace("/", "")
  if(parentFolderPath != null and parentFolderPath.endsWith("/")) parentFolderPath = parentFolderPath[0..-2]

  if(childId == null) do
    if(parentFolderPath == null)
      diff(null, {dis: folderName, emptyFolder, icon: "icon-folder"}.set(tagToAdd, marker()), {add}).commit
    else
      diff(null, {dis: folderName, emptyFolder, icon: "icon-folder", folderPath: parentFolderPath}.set(tagToAdd, marker()), {add}).commit
  end else if(readById(childId).has("emptyFolder")) do
    if(parentFolderPath == null or parentFolderPath == "") parentFolderPath = readById(childId)->dis
    else parentFolderPath = parentFolderPath + (if(parentFolderPath.endsWith("/")) "" else "/") + readById(childId)->dis

    diff(null, {dis: folderName, emptyFolder, icon: "icon-folder", folderPath: parentFolderPath}.set(tagToAdd, marker()), {add}).commit
    finHardDelete(childId.readById)
  end else do
    if(parentFolderPath == null or parentFolderPath == "") parentFolderPath = folderName
    else parentFolderPath = parentFolderPath + (if(parentFolderPath.endsWith("/")) "" else "/") + folderName

    readById(childId).diff({folderPath: parentFolderPath + "/"}).commit
  end
end


def ​

func:finCreateFolderPath ​

finCreateFolderPath(id: null, filterFor) ​

Axon function


meta ​

deffunc:finCreateFolderPath
isfunc
liblib:finStackMobile
namefinCreateFolderPath
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(id: null, filterFor) => do
  currentPaths: try eval("secureReadAll(" + filterFor + ")").findAll(v => v.has("folderPath")).unique("folderPath") catch []
  body: [
    {
      name: "existing",
      editorType: "combobox",
      prompt: toLocale("finStackMobileExt::existingPathPrompt")+":",
      dataProvider: if(currentPaths.isEmpty) "[{folderPath: toLocale(\"finStackMobileExt::newPath\")}]" else "[{folderPath: toLocale(\"finStackMobileExt::newPath\")}].addAll(secureReadAll(" + filterFor + ").findAll(v => v.has(\"folderPath\")).unique(\"folderPath\").toRecList)",
      labelField: "folderPath",
      selectedValueTags: "folderPath",
      defIndex: 0
    },

    {
      name: "newPath",
      editorType: "textinput",
      prompt: toLocale("finStackMobileExt::newPathPrompt")+":"
    },

    {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
    {name: "applyButton", editorType: "button", label: toLocale("finStackExt::coreApply"), controlBar: true}
  ]

  if(id == null)
    body = body.add({name: "record", editorType: "combobox", prompt: toLocale("finStackMobileExt::selectWhich")+" " + filterFor + " "+toLocale("finStackMobileExt::toAddFolderPath")+": ", dataProvider: "secureReadAll(" + filterFor + ")",
    labelField: "dis", selectedValueTags: "id"})

  { "dis": toLocale("finStackMobileExt::addFolderPath"),
  "name": "finCreateFolderPath",
  "body": body.toJSON,
  "cancelButton": "\$cancelButton",
  "commitButton": "\$applyButton",
  "commitAction": "finCreateFolderPathCommit(" + id.toAxonCode + ", \$existing, \$newPath)",
  "finForm": marker()
  }.toGrid.addMeta({formExecute: marker()})
end


def ​

func:finCreateProjectForm ​

finCreateProjectForm(preFill: null) ​

Axon function


meta ​

deffunc:finCreateProjectForm
isfunc
liblib:finStackMobile
namefinCreateProjectForm
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(preFill: null) => do
  nameDef: ""
  disDef: ""
  desDef: ""

  if(preFill != null) do
    nameDef = preFill->name
    disDef = preFill->display
    desDef = preFill->des
  end

  body: [
    {
      name: "name",
      editorType: "textinput",
      prompt: toLocale("finStackMobileExt::hostProjectName")+":",
      defVal: nameDef
    },

    {
      name: "display",
      editorType: "textinput",
      prompt: toLocale("finStackMobileExt::hostDisplayName")+":",
      defVal: disDef
    },

    {
      name:"des",
      editorType: "textarea",
      prompt: toLocale("finStackExt::hostDescription")+":",
      height: 175,
      defVal: desDef
    },

    {
      name:"cancelButton",
      editorType:"button",
      label:toLocale("finStackExt::cancel"),
      controlBar:true
    },

    {
      name:"commitButton",
      editorType:"button",
      label:toLocale("finStackExt::coreCreate"),
      controlBar:true
    }
  ]

  if(preFill != null) do
    if(nameDef.isEmpty) msg: toLocale("finStackMobileExt::emptyProjectPrompt")
    else if(nameDef.contains(" ")) msg: toLocale("finStackMobileExt::nameSpaceProjectPrompt")
    else if(nameDef.size < 4) msg: toLocale("finStackMobileExt::charNameProjectPrompt")
    else if(nameDef != nameDef.decapitalize) msg: toLocale("finStackMobileExt::capitalNameProjectPrompt")
    else if(not nameDef[0].isAlpha) msg: toLocale("finStackMobileExt::firstLetterProjectPrompt")
    else msg: toLocale("finStackMobileExt::errorProjectName")
    body = body.insert(0, {name: "errLabel", editorType: "separator", label: "** "+msg+" **"})
    body = body.add({name: "errLabel", editorType: "separator", label: "** "+msg+" **"})
  end

  { "dis": toLocale("finStackMobileExt::newProjectTitle"),
    "name":if(preFill == null) "finCreateProjectForm" else "finCreateProjectForm" + random(1..10000),
    "body":body.toJSON,
    "width": 450,
    "cancelButton": "\$cancelButton",
    "commitButton":"\$commitButton",
    "commitAction": "if(\$name.isEmpty or \$name.size < 4 or \$name != \$name.toTagName) finCreateProjectForm({name: \$name, display: \$display, des: \$des}) else finCreateProject(\$name, \$display, [].toGrid, \$des)",
    "completeAction": "window.app.ObtainMenu('su', '{{targetRef}}', 'projects', {funcCall: \"finHostMenu('su')\", header: \""+toLocale("finStackMobileExt::hostFinHost")+"\"})",
    "finForm": marker()
  }.toGrid.addMeta({formExecute: marker()})
end


def ​

func:finDBCreateNewEquipCommit ​

finDBCreateNewEquipCommit(equipName, navKind, parent: null, pointSettings: null) ​

Axon function


meta ​

deffunc:finDBCreateNewEquipCommit
isfunc
liblib:finStackMobile
namefinDBCreateNewEquipCommit
overridable✓
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(equipName, navKind, parent: null, pointSettings: null) => do
  // if a point is being created from point library, do nothing
  if (pointSettings != null and pointSettings->createFromLib == true)
    return null

  // all other cases: equip, floor, point not from lib, etc
  rawNavList: read(navMeta)->equipPath.split("/")
  navList: rawNavList.map(r => reFind(r"[a-zA-Z_0-9]+", r))

  if(navKind == true)
    navKind = navList[1]

  newItem: {justAdded}.set(navKind, marker())

  if(navKind == "point") do
    if(pointSettings->kind == "enum") pointSettings = pointSettings.merge({kind: "Str", enum: ""})

    newItem = newItem.merge(pointSettings.merge({-createFromLib, aux}))
  end

  if(parent != null) do
    parentRec: readById(parent)
    parentKind: if(parent != null) parentRec.finNavMetaWhoAmI else ""
    parentIndex: navList.index(parentKind)
    realParentIndex: navList.index(navKind) - 1
    realParent: navList[realParentIndex]

    //check if immediate parent
    if(parentKind == "equip" and navKind == "equip")
      newItem = newItem.set("equipRef", parent)
    else if(realParent != parentKind and realParent != "" and parentIndex > realParentIndex)
      newItem = newItem.set(realParent + "Ref", parentRec[realParent + "Ref"])
    else if((realParent == parentKind and realParent != "") or (realParent != parentKind and realParent != "" and rawNavList[realParentIndex] == "["+realParent+"]" and parentIndex < realParentIndex))
      newItem = newItem.set(parentKind+"Ref", parent)
    //else if(realParent != "")
      //newItem = newItem.set(parentKind+"Ref", parent)

    if (navKind == "point") //tz tag is only added to points
    do
      site: try readById(parentRec->siteRef, false) catch null
      if (site != null)
      do
        if (site["tz"] != null)
          newItem = newItem.set("tz", site->tz) // use the parent site record's timezone
        else
          newItem = newItem.set("tz", now().tz())
      end
      else
      do
        newItem = newItem.set("tz", now().tz())
      end
    end

    if(parentKind != "") do
      navList.each x => do
        if(newItem[x+"Ref"] == null and parentRec[x+"Ref"] != null)
          newItem = newItem.set(x+"Ref", parentRec[x+"Ref"])
      end
    end
  end

  if(navKind == "floor" or navKind == "site") newItem = newItem.set("dis", equipName)
  else if (parent != null)
    newItem = newItem.merge({
      navName: equipName,
      disMacro: if (navKind == "equip") "\$"+navList[1]+"Ref \$navName" else "\$"+realParent+"Ref \$navName"
    })
  else newItem = newItem.merge({navName: equipName})

  if(navKind == navList[1]) newItem = newItem.set("tz", now().tz)

  diff(null, newItem, {add}).commit
end


def ​

func:finDbBuilderMenuItem ​

finDbBuilderMenuItem() ​

Axon function


meta ​

deffunc:finDbBuilderMenuItem
finStackMobileMenu✓
isfunc
liblib:finStackMobile
namefinDbBuilderMenuItem
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

() => do
  projName: context()->projName

  [
    {
      displayName: toLocale("finStackMobileExt::rightMenuDBBuilder"),
      link: "",
      appId: "builder",
      icon: "icon-stack",
      iconType: "class",
      hasBadge: false,
      badgeValue: "15",
      badgeType: "normal",
      action: "app.NavigateToApp('_builder', undefined, false, ['lhs=builder'])",
      level: 0,
      ui: "html",
      classes:"tablet-only-hidden mobile-hidden",
      order: 102,
      keepOpen: true,
    }
  ]
end


def ​

func:finDbHaystackFindUniqueEquipTypes ​

finDbHaystackFindUniqueEquipTypes(conn, filter, percentMatch, applyTags, tag) ​

Axon function


meta ​

deffunc:finDbHaystackFindUniqueEquipTypes
isfunc
liblib:finStackMobile
namefinDbHaystackFindUniqueEquipTypes

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function


def ​

func:finDbHaystackNodeSelectAction ​

finDbHaystackNodeSelectAction(queryStr, nodeTypeStr) ​

Axon function


meta ​

deffunc:finDbHaystackNodeSelectAction
isfunc
liblib:finStackMobile
namefinDbHaystackNodeSelectAction

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function


def ​

func:finDbHaystackReadAllPoints ​

finDbHaystackReadAllPoints(connectorRef, branchFilter, iteration) ​

Axon function


meta ​

deffunc:finDbHaystackReadAllPoints
isfunc
liblib:finStackMobile
namefinDbHaystackReadAllPoints

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function


def ​

func:finDbRelationshipAddEdit ​

finDbRelationshipAddEdit(curItem: null, folderPath: null) ​

Axon function


meta ​

dbAddEdit✓
deffunc:finDbRelationshipAddEdit
isfunc
liblib:finStackMobile
namefinDbRelationshipAddEdit
private✓
relationshipTree✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(curItem:null, folderPath:null) => do
  // local vars with adding a new item values
  disDef: ""
  nameRefDef: ""
  refFilterDef: ""
  childFilterDef: ""
  titleStr: toLocale("finStackMobileExt::addRelationship")
  errMsgs: []

  // editing an item or refill
  if (curItem != null)
  do
    disDef = curItem["dis"]
    nameRefDef = curItem["nameRef"]
    refFilterDef = curItem["refFilter"]
    childFilterDef = curItem["childrenFilter"]
    titleStr = toLocale("finStackMobileExt::editRelationship")

    // add error messages if refill
    if (curItem.has("isRefill"))
    do
      if (disDef == null or disDef.isEmpty())
        errMsgs = errMsgs.add({name: "errMsg1", editorType: "label", text: toLocale("finStackMobileExt::enterRelationshipName")})

      if (nameRefDef == null or nameRefDef.isEmpty())
        errMsgs = errMsgs.add({name: "errMsg2", editorType: "label", text: toLocale("finStackMobileExt::enterReferenceName")})

      if (refFilterDef == null or refFilterDef.isEmpty() or (try parseFilter(refFilterDef) catch null) == null)
        errMsgs = errMsgs.add({name: "errMsg3", editorType: "label", text: toLocale("finStackMobileExt::enterFilterForReference")})

      if (childFilterDef == null or childFilterDef.isEmpty() or (try parseFilter(childFilterDef) catch null) == null)
        errMsgs = errMsgs.add({name: "errMsg4", editorType: "label", text: toLocale("finStackMobileExt::enterFilterForChildren")})
    end
  end

  // generate and return form data needed by finFormDBAddEdit
  return {
    title: titleStr,
    body: errMsgs.addAll([
      {
        name: "disInput",
        prompt: toLocale("finStackMobileExt::relationshipName"),
        editorType: "textinput",
        defVal: disDef
      }, // not isEmpty(\$disInput)

      {
        name: "nameRefInput",
        prompt: toLocale("finStackMobileExt::nameOfRef"),
        editorType: "textinput",
        defVal: nameRefDef
      }, // not isEmpty(\$nameRefInput)

      {
        name: "refFilterInput",
        prompt: toLocale("finStackMobileExt::refFilter"),
        editorType: "textinput",
        defVal: refFilterDef
      },   // not isEmpty(\$refFilterInput) and parseFilter(\$refFilterInput, false) != null

      {
        name: "childrenFilterInput",
        prompt: toLocale("finStackMobileExt::childrenFilter"),
        editorType: "textinput",
        defVal: childFilterDef
      } // not isEmpty(\$childrenFilterInput) and parseFilter(\$refFilterInput, false) != true
    ]),

    validation: "not isEmpty(\$disInput) and not isEmpty(\$nameRefInput) and (not isEmpty(\$refFilterInput) and (try parseFilter(\$refFilterInput, false) catch null) != null) and (not isEmpty(\$childrenFilterInput) and parseFilter(\$refFilterInput, false) != true)",
    dictAsStr: "{relationship, dis: \$disInput, nameRef: \$nameRefInput, refFilter: \$refFilterInput, childrenFilter: \$childrenFilterInput}",
    //refillDictAsStr: "{dis: \$disInput, nameRef: \$nameRefInput, refFilterInput: \$refFilterInput, childrenFilter: \$childrenFilterInput}"
  }
end


def ​

func:finDbSavedFiltersTreeSelectAction ​

finDbSavedFiltersTreeSelectAction(selectedRef: "") ​

Creates panels to be displayed on when an item from the savedFilters tree is selected.

These panels will include a data grid of all the savedFilters.


meta ​

constructfinDbSavedFiltersTreeSelectAction()
deffunc:finDbSavedFiltersTreeSelectAction
isfunc
liblib:finStackMobile
namefinDbSavedFiltersTreeSelectAction
overridable✓
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(selectedRef: "") => do
  selectFunc: ""
  title: toLocale("finStackMobileExt::savedFilters")
  addButtonAction: ""
  deleteButtonAction: ""
  editButtonAction: ""
  deleteButtonEnable: ""
  editButtonEnable: ""

  if(selectedRef.isStr)
  do
    if(not selectedRef.isEmpty)
    do
      if(selectedRef.startsWith("@"))
      do
        folderRec: readById(selectedRef[1..-1].parseRef, false)

        if(folderRec != null)
            title = toLocale("finStackMobileExt::itemInObj").replace("{itemName}", title).replace("{objectName}", folderRec.dis)
      end else
        title = toLocale("finStackMobileExt::itemInObj").replace("{itemName}", title).replace("{objectName}", selectedRef.split("/")[-1])

      addButtonAction = "finFormDBAddEdit(\"savedQueryFilter\", null, null, "+selectedRef.toAxonCode+")"
    end else
      addButtonAction = "finFormDBAddEdit(\"savedQueryFilter\", null, null, null, true)"

    deleteButtonAction = "finFormDBBuilderDelete(({{args.selectedItems}}).map(r => {id: try r->id.replace(\"@\", \"\").parseRef catch r->id->val.replace(\"@\", \"\").parseRef, dis:r->dis}), null, null, \"savedQueryFilter\", \"{{args.selectedItems[0].folderPath}}\")"
    deleteButtonEnable = "args.selectedItems.length > 0"

    editButtonAction = "finFormDBAddEdit(\"savedQueryFilter\", {id: {{args.selectedItems[0].id}}, dis: \"{{args.selectedItems[0].dis}}\"}, null, \"{{args.selectedItems[0].folderPath}}\")"
    editButtonEnable = "args.selectedItems.length == 1"

    selectFunc = "dbMakeDataGridPanel(\"finFilteredFuncEval(savedQueryFilter, filterString).addRows(readAll(savedQueryFilter and not func))\", \"savedQueryFilter\", "+selectedRef.toAxonCode+")"
  end else
  do
    saveFilterRec: readById(selectedRef)
    title = title + " - " + toLocale("finStackMobileExt::resultsForSavedFilter").replace("{savedFilter}", saveFilterRec.dis)
    selectFunc = "dbMakeDataGridPanel(\"finFilteredFuncEval(savedQueryFilter, filterString).addRows(readAll(savedQueryFilter and not func)).findAll(v => v->id == "+selectedRef.toAxonCode+")[0]->filterString.parseFilter.readAll\", \"savedQueryFilter\")"

    addButtonAction = "finFormDBAddEdit(\"savedQueryFilter\", null, null, "+saveFilterRec["folderPath"].toAxonCode+")"
    deleteButtonAction = "finFormDBBuilderDelete("+selectedRef.toAxonCode+", null, null, \"savedQueryFilter\", "+saveFilterRec["folderPath"].toAxonCode+")"
    editButtonAction = "finFormDBAddEdit(\"savedQueryFilter\", {id: "+selectedRef.toAxonCode+", dis: "+saveFilterRec.dis.toAxonCode+"}, null, "+saveFilterRec["folderPath"].toAxonCode+")"
  end

  buttonList: [
    {
      label: toLocale("finStackExt::add"),
      icon: "ic|icon-plus",
      action : {type: "axon", action: addButtonAction}
    },

    {
      label: toLocale("finStackExt::delete"),
      icon: "ic|icon-minus",
      enableWhen: deleteButtonEnable,
      action : {type: "axon", action: deleteButtonAction},
    },

    {
      label: toLocale("finStackExt::coreEdit"),
      icon: "ic|icon-document-edit",
      enableWhen: editButtonEnable,
      action : {type: "axon", action: editButtonAction}
    }
  ]

  return {
    panels:[
      {
        view: "default",
        viewId: "savedFiltersMainPanel",
        panelTitle: title,
        dis: toLocale("finStackMobileExt::editSavedFilter"),
        default: true,
        resolveWith: { type: "axon", action: selectFunc },
        buttons: buttonList
      }
    ]
  }
end


def ​

func:finDbSavedQueryFilterAddEdit ​

finDbSavedQueryFilterAddEdit(curItem: null, folderPath: null) ​

Axon function


meta ​

dbAddEdit✓
deffunc:finDbSavedQueryFilterAddEdit
isfunc
liblib:finStackMobile
namefinDbSavedQueryFilterAddEdit
overridable✓
private✓
savedQueryFilterTree✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(curItem:null, folderPath:null) => do
  titleStr: toLocale("finStackMobileExt::addSavedFilter")
  dictStr: "{dis: \$filterName, filterString: \$filterInput, savedQueryFilter}"
  nameDef: ""
  filterDef: ""
  errMsgs: []

  /*
    if editing a record
    get the current values
  */
  if (curItem != null)
  do
    nameDef = curItem["dis"]
    filterDef = curItem["filterString"]

    /*
      if invalid user input
      get user input
      add error messages
    */
    if (curItem.has("isRefill"))
    do
      if (nameDef == null or nameDef.isEmpty()) errMsgs = errMsgs.add({name: "errMsg1", editorType: "label", text: toLocale("finStackMobileExt::enterName")})
      if (filterDef == null or filterDef.isEmpty() or parseFilter(filterDef, false) == null) errMsgs = errMsgs.add({name: "errMsg2", editorType: "label", text: toLocale("j2FinToolsExt::enterValidFilter")})
    end
    else titleStr = toLocale("finStackMobileExt::editSavedFilter")
  end

  // generate and return form data needed by finFormDBAddEdit
  return {
    title: titleStr,

    // elements to be added to body
    body: errMsgs.addAll([
      {name: "filterName", editorType: "textinput", prompt: toLocale("finStackExt::gbName") + ":", defVal: nameDef},
      {name: "filterInput",editorType: "textinput", prompt: toLocale("finStackExt::finFilter") + ":", defVal: filterDef},
    ]),

    // answers yes to: "is this valid input?"
    validation: "not isEmpty(\$filterInput) and parseFilter(\$filterInput, false) != null and not isEmpty(\$filterName)",

    // what the new record should look like
    dictAsStr: dictStr
  }
end


def ​

func:finDbTagBundleAddEdit ​

finDbTagBundleAddEdit(curItem: null, folderPath: null) ​

Axon function


meta ​

dbAddEdit✓
deffunc:finDbTagBundleAddEdit
isfunc
liblib:finStackMobile
namefinDbTagBundleAddEdit
overridable✓
private✓
tagBundleTree✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(curItem:null, folderPath:null) => do
  titleStr: toLocale("finStackMobileExt::addTagBundle")
  dictStr: "{description: \$descInput, tagBundle, dis: \$disInput, addTags: \$addInput, removeTags: if(not isEmpty(\$removeInput)) (\$removeInput).split(\",\").map(r => if(not r.startsWith(\"-\")) \"-\" + r else r).concat(\",\") else \"\", allowFilter: \$filterInput, trackBundle: if(\$trackBundleCb) marker() else removeMarker(), \$bundleType}"
  nameDef: ""
  filterDef: ""
  addDef: ""
  removeDef: ""
  descDef: ""
  trackBundleDef: false
  bundleTypeDef: 0
  errMsgs: []

  if (curItem != null)
  do
    nameDef = curItem["dis"]
    filterDef = curItem["allowFilter"]
    addDef = curItem["addTags"]
    removeDef = curItem["removeTags"]
    descDef = curItem["description"]
    trackBundleDef = curItem.has("trackBundle")
    bundleTypeDef = if (curItem.has("alarmConfig")) 1 else if (curItem.has("hisConfig")) 2 else 0

    if (curItem.has("isRefill"))
    do
      if (nameDef.isEmpty) errMsgs = errMsgs.add({name: "errMsg1", editorType: "label", text: toLocale("finStackMobileExt::enterName")})
      if (not filterDef.isEmpty and parseFilter(filterDef, false) == null) errMsgs = errMsgs.add({name: "errlabel", editorType: "label", text: toLocale("finStackMobileExt::invalidAllowFilter")})
    end
    else titleStr = toLocale("finStackMobileExt::editTagBundle")
  end

  return {
    title: titleStr,

    body: errMsgs.addAll([
      {
        name: "disInput",
        editorType: "textinput",
        prompt: toLocale("finStackMobileExt::reportColName") + ":",
        defVal: nameDef
      },

      {
        name: "descInput",
        editorType: "textarea",
        prompt: toLocale("finStackMobileExt::hostDescription") + ":",
        defVal: descDef,
        maxHeight: 125
      },

      {
        name: "addInput",
        editorType: "textinput",
        prompt: toLocale("finStackMobileExt::tagBundlesTagsToAddTitle") + ":",
        defVal: addDef
      },

      {
        name: "removeInput",
        editorType: "textinput",
        prompt:  toLocale("finStackMobileExt::tagBundlesTagsToRemoveTitle") + ":",
        defVal: removeDef
      },

      {
        name: "filterInput",
        editorType: "textinput",
        prompt: toLocale("finStackMobileExt::allowFilter") + ":",
        defVal: filterDef
      },

      {
        name: "bundleType",
        editorType: "combobox",
        prompt: toLocale("finStackMobileExt::configType") + ":",
        dataProvider: [{dis: "None", val: null}, {dis: "Alarm Config", val: "alarmConfig"}, {dis: "His Config", val: "hisConfig"}].toAxonCode,
        labelField: "dis",
        selectedValueTags: "val",
        defIndex: bundleTypeDef
      },

      {
        name: "trackBundleCb",
        editorType: "checkbox",
        label: toLocale("finStackMobileExt::tagBundlesTrack") + ":", //Application
        defVal: trackBundleDef
      }
    ]),

    validation: "(isEmpty(\$filterInput) or parseFilter(\$filterInput, false) != null) and not isEmpty(\$disInput)",
    dictAsStr: dictStr
  }
end


def ​

func:finDbTemplateAddEdit ​

finDbTemplateAddEdit(curItem: null, folderPath: null) ​

Axon function


meta ​

dbAddEdit✓
deffunc:finDbTemplateAddEdit
isfunc
liblib:finStackMobile
namefinDbTemplateAddEdit
private✓
templateTree✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(curItem: null, folderPath: null) => do
  titleStr: toLocale("finStackMobileExt::editTemplate")
  disDef: if (curItem.has("displayName")) curItem->displayName else curItem.dis
  templateOnDef: curItem["templateOn"]
  funcTempDef: if (curItem["funcTemplate"] == null) "finConnectorTemplatePackageAddDevice(\$this, @\$id, \"<data>\")" else curItem["funcTemplate"]
  dictStr: "{templateOn: \$templateOnInput, funcTemplate: \$templateFunc, displayName: \$tempDis, dis: if (endsWith(\$tempDis, \".fst\")) \$tempDis else \$tempDis + \".fst\"}"
  errMsgs: []

  if(curItem.has("isRefill"))
    errMsgs = errMsgs.add({name: "errMsg", editorType: "label", text: toLocale("finStackMobileExt::invalidTemplateOn")})

  return {
    title: titleStr,

    body: errMsgs.addAll([
      {
        name: "tempDis",
        editorType: "textinput",
        prompt: toLocale("finStackMobileExt::templateNumber"),
        defVal: disDef
      },

      {
        name: "templateOnInput",
        editorType: "textinput",
        prompt: "templateOn:",
        defVal: templateOnDef
      },

      {
        name: "templateFunc",
        editorType: "textinput",
        prompt: "funcTemplate:",
        defVal: funcTempDef
      }
    ]),

    validation: "parseFilter(\$templateOnInput, false) != null and not isEmpty(\$tempDis)",
    dictAsStr: dictStr
  }

end


def ​

func:finDbTopicAdd ​

finDbTopicAdd(folderPath: null) ​

Axon function


meta ​

deffunc:finDbTopicAdd
isfunc
liblib:finStackMobile
namefinDbTopicAdd
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(folderPath: null) => do
  title: toLocale("finStackMobileExt::newTopic")
  body: [
    {name: "typeRBsLabel", editorType: "label", text: toLocale("finStackMobileExt::newTopicPrompt")},
    {name: "topicType", editorType: "radio", label: toLocale("finStackMobileExt::alarmTopic"), selectedValue: "finCreateAlarmTopicForm", encapsulate: false, defVal: true},
    {name: "topicType", editorType: "radio", label: toLocale("finStackMobileExt::noteTopic"), selectedValue: "finCreateNoteTopicForm", encapsulate: false},
    {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
    {name: "applyButton", editorType: "button", label: toLocale("finStackExt::next"), controlBar: true}
  ]

  if (folderPath.isStr and folderPath.startsWith("@")) do
    folderRec: readById(folderPath[1..-1].parseRef, false)
    if (folderRec != null)
      folderPath = if (folderRec["folderPath"] != null) folderRec->folderPath + "/" + folderRec.dis else folderRec.dis
  end

  return {
    "dis": title,
    "name": "addTopicForm",
    "body": body.toJSON,
    "cancelButton": "\$cancelButton",
    "commitButton": "\$applyButton",
    "commitAction": "\$topicType("+(if(folderPath != null) "null, " + folderPath.toAxonCode else "")+")",
    "finForm": marker()
  }.toGrid.addMeta({formExecute: marker()})
end


def ​

func:finEquipCharts ​

finEquipCharts(equ, rng: today) ​

Function to generate chart for equip with schedules and alarms. Alpha Release.


meta ​

chartOnequip and not baId and not hidden
deffunc:finEquipCharts
disFinEquipCharts
excludessystemOne
finSavedChart✓
isfunc
liblib:finStackMobile
namefinEquipCharts
private✓
queryStringfinEquipCharts($targetRef)

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(equ, rng: today) => do
  equ = equ.toRecId
  try do
    lst: eval("secureReadAll(point and his and "+ finNavMetaWhoAmI(equ.toRec) +"Ref== " + equ.toAxonCode + ")").finHisReadBaselineCore(rng,null,null,null) //points with his
  end catch lst: [].toGrid

  try do
    if(lst[0].size == 0) do
      hs: now()
      he: now()
    end
    else do
      hs: lst[0].meta->hisStart
      he: lst[0].meta->hisEnd
    end
  end catch do
    hs: now()
    he: now()
  end

  tmp: []
  fintmp: []
  nams: []
  typs: []
  cou: 0
  typ: ""
  filler: {number: 0, str: "", bool: false}

  try do
    am: navFilter("alarmTarget", equ, null).alarms(rng) //alarms
    am.each x=> try do
      nams = nams.add("Alarm: "+ readById(x->targetRef).dis)
      typs = typs.add("Bool")
      tmp = []
      x->periods.parseDiscretePeriods.each y=> do
        tmp = tmp.addAll([{ts: hs + y->offset}.set("v"+cou,true),{ts: hs + y->offset + y->dur}.set("v"+cou,false)])
      end
      lst = lst.add(tmp.toGrid.addMeta({dis: "Compare Recent", view: "chart", hisLimit: 10000, hisStart: hs, hisEnd: he
        }).addColMeta("ts",{tz: hs.tz, dis:"Timestamp", chartFormat:"ka"}).addColMeta("v"+cou,{dis: nams[cou], kind: typs[cou]}))
      cou = cou + 1
    end catch 0
  end catch 0

  try do
    sch: eval("secureReadAll(scheduleRef and point and "+ finNavMetaWhoAmI(equ.toRec) +"Ref==" + equ.toAxonCode + ")") //schedules
    sch.each x=> try do
      nams = nams.add("Schedule: "+ x.dis)
      typs = typs.add(x.scheduleHis(rng).find(y=> y.has("val"))->val.debugType.split(":")[2])
      tmp = []
      x.scheduleHis(rng).map(y=> if(y.has("val")) y else y.set("val", filler.trap(typs[cou].lower))).renameCol("val","v0").each y=> do
        tmp = tmp.add(y)
      end
      lst = lst.add(tmp.toGrid.addMeta({dis: "Compare Recent", view: "chart", hisLimit: 10000, hisStart: hs, hisEnd: he
        }).addColMeta("ts",{tz: hs.tz, dis:"Timestamp", chartFormat:"ka"}).addColMeta("v0",{dis: nams[cou], kind: typs[cou]}))
      cou = cou + 1
    end catch 0
  end catch 0

  lst
end
//parseDiscretePeriods
//read(equip and siteRef->dis=="City Center" and navName=="Vav-10").finEquipCharts()
//function appends alarms and schedules to output of finHisReadBaseline
//navFilter("alarmTarget", readAll(equip)[2], null).alarms(today)[0]->periods.parseDiscretePeriods


def ​

func:finEquipRefTree ​

finEquipRefTree(id, treePath: null) ​

Axon function


meta ​

deffunc:finEquipRefTree
isfunc
liblib:finStackMobile
namefinEquipRefTree
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(id, treePath: null) => do
  tree: null
  navKind: readById(id).finNavMetaWhoAmI()
  targetTags: finUniqueTags(parseFilter("id == @"+id))[0]->markers.split(",").findAll(v => v != navKind and readAll(parseFilter(v+"Ref == @"+id)).size > 0)
  equipsWithRefs: []

  if(treePath == null) do
    tree = readByIds([id]).map(r => r.merge({treePath: "/@" + r->id, treeDisplay: r.dis}))

    targetTags.each tag => do
      equipsWithRefs = equipsWithRefs.addAll(readAll(parseFilter(tag+"Ref == @"+id+" and equip"))
        .map(r => r.merge({treePath: "/@" + r->id, treeDisplay: tag + "Ref " + r.dis}))
        .sort((a, b) => a.dis<=>b.dis)
        .toRecList
      )
    end

    if(equipsWithRefs.size > 0) tree = tree.addRows(equipsWithRefs)
  end else
    tree = finNavChildren("equip", treePath.split("/")[-1][1..-1].parseRef()).map(r => if(r.has("point")) r.merge({-treePath}) else r.set("treePath", treePath + "/@" + r->id)).sort((a, b) => a.dis<=>b.dis)

  tree
end


def ​

func:finExtSettingsForm ​

finExtSettingsForm(data: null) ​

Axon function


meta ​

deffunc:finExtSettingsForm
isfunc
liblib:finStackMobile
namefinExtSettingsForm
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(data: null) => do
  extList: exts()
  if(not data.isList) do
    body: [
    {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
    {name: "applyButton", editorType: "button", label: toLocale("finStackExt::coreApply"), controlBar: true}
    ]

    comAct: "finExtSettingsForm(["
    count: 0
    extList.each x=> do
      body = body.add({
        name: count+"chkbx", label: x->dis+(if(x.has("app")) " - App" else ""),
        editorType: "checkbox", defVal: if(x->extStatus == "ok") true else false})
      if(x.has("depends") and x->depends.trim != "")
        body = body.add({name: "label", editorType: "label", text: toLocale("finStackMobileExt::extRequires").replace("{name}", x->dis) +
          extList.findAll(y=> x->depends.split(",").index(y->name) != null).colToList("dis").concat(", ")})
      comAct = comAct + "{name: \""+x->name+"\", enab: \$" + count + "chkbx},"
      count = count + 1
    end
    comAct = comAct + "])"

    {"dis": toLocale("finStackMobileExt::extSettings"),
    "name": "finExtSettingsForm",
    "body": body.toJSON,
    "cancelButton": "\$cancelButton",
    "commitButton": "\$applyButton",
    "commitAction": comAct,
    "finForm": marker()
    }.toGrid.addMeta({formExecute: marker()})
  end
  ///////////////////////
  else if(data.isList) do
    tmp: {}

    data.each x=> do
      if(x->enab) do //add
        tmp = extList.find(y=> y->name == x->name)
        //only allow if license lets
        if(readCount(ext==x->name) == 0) do
          if(tmp.has("depends")
          and extList.findAll(y=> tmp->depends.split(",").index(y->name) != null).finGridFilter(not enabled).size < 1) do
            diff(null,{ext: x->name},{add}).commit
            extList = extList.map(y=> if(y->name == x->name) y.set("enabled",marker()) else y)
          end
        end
      end
      else do //remove
        readAll(ext==x->name).finHardDelete
        extList = extList.map(y=> if(y->name == x->name) y.remove("enabled") else y)
      end
    end

  end
end


def ​

func:finFavoritesForm ​

finFavoritesForm(newnotremove: true, url: null, data: null) ​

Axon function


meta ​

deffunc:finFavoritesForm
isfunc
liblib:finStackMobile
namefinFavoritesForm
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(newnotremove:true, url:null, data: null) => do
  if(not data.isDict) do
    formdict: {
    "dis": toLocale("finStackMobileExt::createFavoriteTitle"),
    "name": "finFavoritesForm",
    "cancelButton": "\$cancelButton",
    "commitButton": "\$commitButton",
    "commitAction": "null",
    "completeAction": "window.app.RefreshLauncher()", //make this refresh the main menu
    "finForm": marker()
    }

    body: [
    {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
    {name: "commitButton", editorType: "button", label: toLocale("finStackExt::ok"), controlBar: true}
    ]

    if(newnotremove) do //add entries
      folderopts: [{id: @null, dis: toLocale("finStackMobileExt::rootLevel")}].toGrid.addRows(readAll(favorite).sort("dis")).toRecList.toAxonCode

      body = body.add({name: "name", editorType: "textinput", prompt: toLocale("finStackMobileExt::reportColName")+":", defVal: ""}) //name

      body = body.add({
        name: "icon",
        editorType: "ractive",
        ractiveType: "multiselect",
        prompt: toLocale("finStackExt::finIcon"), //icon
        data: finGetIconMultiSelectData(),
        autoClose: true,
        selectedValueTags: "icon",
        singleSelect: true,
        placeholder:toLocale("finStackExt::selectItems")
      })

      body = body.add({name: "folder", editorType: "combobox", prompt: toLocale("finStackExt::saveAsFolderPath"),
        dataProvider: folderopts, labelField: "dis", selectedValueTags: "id", defIndex: 0}) //folder

      formdict = formdict.set("commitAction","finFavoritesForm("+newnotremove+","+url.toAxonCode+",{name:\$name, icon: \$icon, folder: \$folder})")
    end else do //remove entries
      entrys: []

      readAll(favorite).sort("dis").each x=> do
        entrys = entrys.add({id: x->id, dis: x.dis})
        cnt: 0
        if(x.has("submenu")) x->submenu.fromJSON->items.toGrid.sort("label").each y=> do
          entrys = entrys.add({id: x->id + " " + cnt, dis: x->dis+" > "+y->label})
          cnt = cnt + 1
        end
      end

      body = body.add({name: "delete", editorType: "combobox", prompt: toLocale("finStackMobileExt::favoriteToDelete"),
        dataProvider: entrys.toAxonCode, labelField: "dis", selectedValueTags: "id", defIndex: 0})
      formdict = formdict.set("commitAction","finFavoritesForm("+newnotremove+",null,{id: \$delete})")
        .set("dis",toLocale("finStackMobileExt::deleteFavoriteTitle"))
    end

    formdict.set("body", body.toJSON).toGrid.addMeta({formExecute: marker()})
  end
  ///////
  else do
    //commit the stuff with order, url, name, icon, favorite
    if(newnotremove) do
      counter: -0.01 //reset orders on the favorites
      readAll(favorite).toRecList.each fav=> do
        counter = counter + 0.01
        fav.diff({order: counter}).commit
      end
      counter = counter + 0.01
      icon: data->icon
      if(icon.size == 0) icon = "icon-question"
      else icon = icon[0]->icon

      if(data->folder == @null) diff(null,{order: counter, url: url, dis: data->name, icon: icon, favorite},{add}).commit
      else do //get record and add submenu
        folder: data->folder.readById
        pointVars: { items: [] }
        if(folder.has("submenu")) pointVars = folder->submenu.fromJSON
        pointVars = pointVars.set("items", pointVars->items.add(
          {label: data->name, icon: icon, action: "window.location.href = '"+url+"'", keepOpen: true}))
        folder.diff({submenu: pointVars.toJSON}).commit
      end
    end
    ///////
    else do
      if(data->id.isRef) finHardDelete(data->id)
      else do
        data = data->id.split(" ")
        data = {id: data[0].parseRef, indx: data[1].parseNumber}
        subm: data->id.readById->submenu.fromJSON->items.remove(data->indx)
        if(subm.size == 0) data->id.readById.diff({-submenu}).commit
        else data->id.readById.diff({submenu: toJSON({items:subm}) }).commit
      end
    end
  end
end


def ​

func:finFavoritesMenu ​

finFavoritesMenu(target: null) ​

Axon function


meta ​

deffunc:finFavoritesMenu
finStackMobileMenu✓
isfunc
liblib:finStackMobile
namefinFavoritesMenu
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(target: null) => do
  pointVars: {
    items: [
      {
        label: toLocale("finStackExt::add"),
        icon: "icon-document-edit",
        tooltip: toLocale("finStackMobileExt::editMobileHeader"),
        action: "finstack.eval('finFavoritesForm(true,\"'+ '/'+window.location.href.replace('://','_').split('/').splice(1,1000000).join('/') +'\")')",
        keepOpen: true
      },{
        label: toLocale("finStackExt::remove"),
        icon: "icon-trash",
        tooltip: toLocale("finStackMobileExt::removeMobileHeader"),
        action: "finstack.eval('finFavoritesForm(false)')",
        keepOpen: true
      }
    ]
  }.toJSON

  basicentry: {
    displayName: "",
    link: "",
    appId: "favorites",
    icon: "icon-question",
    iconType: "class",
    action: "null",
    keepOpen: true,
    order: 0.99,
    ui: "html",
  }

  menuitems: [{
    displayName: toLocale("finStackMobileExt::favorites"),
    link: "",
    appId: "favorites",
    icon: "icon-star",
    iconType: "class",
    action: "null",
    submenu: pointVars,
    keepOpen: true,
    order: 2,
    ui: "html",
    }].toGrid

  if(read(favorite, false) != null) menuitems = menuitems.addRow({displayName: toLocale("finStackMobileExt::favorites"), level: 0, isDivider: true, order: -1, appId: "favorites"})

  ordr: -0.99
  readAll(favorite).sort((x,y)=> x->dis.lower <=> y->dis.lower).each fav=> do
    temp: basicentry
    if(fav.has("dis")) temp = temp.set("displayName", fav->dis)
    if(fav.has("icon")) temp = temp.set("icon", fav->icon)
    //if(fav.has("order")) temp = temp.set("order", fav->order)
    temp = temp.set("order",ordr)
    if(fav.has("url")) temp = temp.set("action", "window.location.href = '"+ fav->url +"'")
    if(fav.has("submenu")) temp = temp.set("submenu", {items: fav->submenu.fromJSON->items.toGrid.sort("label").toRecList}.toJSON)
    menuitems = menuitems.addRow(temp)
    ordr = ordr + 0.01
  end

  menuitems
end


def ​

func:finFindNonDbRec ​

finFindNonDbRec(listOfIds) ​

Returns a list of dicts resembling, if not actually, records.

Some trees support custom functions. These functions return record like dicts with custom ids which cannot be found in the database. This function finds these "records" if present as well as ids that can be found in the database.

Supports:

  • tagBundle
  • savedFilter

listOfIds - Can be a list of ids as strings or as refs.


meta ​

constructfinFindNonDbRec(readAll(site).colToList("id"))
deffunc:finFindNonDbRec
isfunc
liblib:finStackMobile
namefinFindNonDbRec
overridable✓
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(listOfIds) => do
  listOfIds.map(r => do
    if(not r.isStr) r = r.toStr
    else r = r.replace("@", "")
    // tag_bundle as id
    if(r.startsWith("savedQueryFilter")) finFilteredFuncEval(savedQueryFilter, filterString).find(v => v->id == r.parseRef)
    else if(r.startsWith("tagBundle")) finFilteredFuncEval(tagBundleFunc, addTags or removeTags).find(v => v->id == r.parseRef)
    else if(r.startsWith("connLearn")) do
      if(r.split(":").size == 4)
        {id: r, connRef: r.split(":")[1].parseRef, learn: r.split(":")[2].parseUri, bacnetCur: r.split(":")[3], point}
      else
        {id: r, connRef: r.split(":")[1..4].concat(":").parseRef, learn: r.split(":")[5].parseUri, bacnetCur: r.split(":")[6], point}
    end
    else if(r.startsWith("folderPath")) {isFolder, id:r}
    else do
      r = r.parseRef.readById(false)

      if (r != null and r.has("connPointDiscovery"))
        return r.merge({point})

      return r
    end
  end).findAll(v => v != null)
end


def ​

func:finFindToolsOnNavItem ​

finFindToolsOnNavItem(navItemRefs: null) ​

Axon function


meta ​

deffunc:finFindToolsOnNavItem
isfunc
liblib:finStackMobile
namefinFindToolsOnNavItem
overridable✓
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(navItemRefs:null) => do
  navItemRef: navItemRefs
  toolList: []

  if (navItemRefs.isList) navItemRef = navItemRefs[0]
  else navItemRefs = [navItemRefs]

  if (navItemRef == null)
    toolList = finFindTools([], true)
  else
    toolList = finFindTools([navItemRef])
    //toolList = finFindTools([navItemRef], "dbBuilder")

  toolList.sort("dis")
    .toRecList
    .map(tool =>
      {
        folderPath: if(tool["folderPath"] != null and not tool->folderPath.trim.isEmpty) tool->folderPath else null,
        label: try tool->dis catch tool.dis,
        type: "axon",
        action: "finRunSelectedTool("+navItemRef.toAxonCode+", "+navItemRefs.toAxonCode+", [{name:"+tool->name.toAxonCode+", src: "+tool->src.toAxonCode+"}])"
      }
    )
end


def ​

func:finFolioDownloadForm ​

finFolioDownloadForm(data: null, app: null) ​

Form to download records with a certain filter, like legacy Folio Download


meta ​

appFormOnfolio
deffunc:finFolioDownloadForm
distoLocale("finStackExt::reportsDownload")
folderPathtoLocale("finStackMobileExt::coreBackup")
isfunc
liblib:finStackMobile
namefinFolioDownloadForm
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(data: null, app: null) => do
  if(data == null or data.isStr) do
    if(not data.isStr) data = ""
    if(data == "program") data = "program or macro"
    if(app == null) ftypes: [
      {a:"Zip (" + toLocale("finStackMobileExt::idsWillBePreserved") + ")",b:".zip"},
      {a:"Trio",b:".trio"},
      {a:"Zinc",b:".zinc"},
      {a:"JSON",b:".json"},
      {a:"CSV (" + toLocale("finStackMobileExt::refTagsMayBeBroken") + ")",b:".csv"}].toAxonCode
    else ftypes: [{a:"Zip (" + toLocale("finStackMobileExt::idsWillBePreserved") + ")",b:".zip"}].toAxonCode

    body: [
      {name: "filter", editorType: "filter", prompt: toLocale("finStackExt::finFilter"), defVal: data},
      {name: "type", editorType: "combobox", prompt: toLocale("finStackMobileExt::fileType"), dataProvider: ftypes, labelField: "a", selectedValueTags: "b", defIndex: 0},
      {name: "name", editorType: "textinput", prompt: toLocale("finStackExt::fileName"), defVal: now().format("YYYYMMDDhhmmss")},
      {name: "pres", editorType: "checkbox", label: toLocale("finStackMobileExt::filePreserveID"), defVal: true},
      {name: "chkbx", editorType: "checkbox", prompt: toLocale("finStackMobileExt::fileRecordSelection"), label: toLocale("finStackExt::fileRecordSelectAll"), defVal: true},
      {name: "list", editorType: "list", listType: "checkbox", labelField: "dis", selectedValueTags: "id", defValTagName: "selected", height: 150,
        dataProvider: "try readAll(parseFilter(\$filter)).map(x=> x.set(\"selected\",\$chkbx).set(\"dis\",x.dis)).sort(\"dis\") catch []"},
      {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
      {name: "commitButton", editorType: "button", label: toLocale("finStackMobileExt::coreBackup"), controlBar: true}
    ]

    {"dis": toLocale("finStackMobileExt::rightMenuFolio")+" "+toLocale("finStackExt::reportsDownload"), //"Folio Download",
    "name": "finFolioDownloadForm1",
    "body": body.toJSON,
    "cancelButton": "\$cancelButton",
    "commitButton": "\$commitButton",
    "commitAction": "finFolioDownloadForm({filter: \$filter, type: \$type, name: \$name, pres: \$pres, selec: \$list})",
    "finForm": marker()
    }.toGrid.addMeta({formExecute: marker()})
  end
  ///////////////////////
  else if(data.isDict) do
    if(data->type == ".zip") do
      t: (g)=> g.toAxonCode
      body: [
      {name: "recs", editorType: "checkbox", label: toLocale("finStackMobileExt::folioBackupIncRefs"), defVal: true},
      {name: "shouldBackupInDb", editorType: "checkbox", label: toLocale("finStackMobileExt::folioBackupInFolio"), defVal: false},
      {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
      {name: "commitButton", editorType: "button", label: toLocale("finStackMobileExt::coreNext"), controlBar: true}
      ]

      {"dis": toLocale("finStackMobileExt::rightMenuFolio")+" "+toLocale("finStackExt::reportsDownload"), //"Folio Download",
      "name": "finFolioDownloadForm2",
      "body": body.toJSON,
      "cancelButton": "\$cancelButton",
      "commitButton": "\$commitButton",
      "commitAction": "finFolioDownloadForm(["+data->filter.t+", "+data->type.t+", "+data->name.t+", "+
        data->pres.t+", \$recs, "+data->selec.t+"])",
      "commitAction": "finFolioDownloadForm(["+data->filter.t+", "+data->type.t+", "+data->name.t+", "+
        data->pres.t+", \$recs, "+data->selec.t+", \$shouldBackupInDb])",
      "finForm": marker()
      }.toGrid.addMeta({formExecute: marker()})
    end else finFolioDownloadForm([data->filter, data->type, data->name, data->pres, false, data->selec])
  end
  /////////////////////// backup file creation stage
  else if(data.isList) do
    bakRec: null
    if(data[5].size == 0) do
      filt: data[0]
      if(filt.trim == "") filt = "id"
      tmp: readAll(parseFilter(filt))
    end else tmp: data[5].toRecList.toGrid
    if(data[3]) tmp = tmp.map(x=> x.set("origId", x->id))
    ftmp: {finBackup: marker(), bak: marker(), dis: data[2]+data[1], file: {bin, mime:"application/octet-stream"}}
    if(data[1]==".zip") do
      if(data[4]) tmp = tmp.finBackupRecord({everything:true})[0]
      else tmp = tmp.finBackupRecord({})[0]
      bakRec = tmp.diff({dis: data[2]+data[1], finBackup: marker(), bak: marker()}).commit
    end
    else if(data[1] == ".csv") bakRec = tmp.ioWriteCsv(ioBin(diff(null,ftmp,{add}).commit->id,"file"))
    else if(data[1] == ".json") bakRec = tmp.ioWriteJson(ioBin(diff(null,ftmp,{add}).commit->id,"file"))
    else if(data[1] == ".trio") bakRec = tmp.ioWriteTrio(ioBin(diff(null,ftmp,{add}).commit->id,"file"))
    else if(data[1] == ".zinc") bakRec = tmp.ioWriteZinc(ioBin(diff(null,ftmp,{add}).commit->id,"file"))
    recId: bakRec->id
    tmp = finFormAlertOk(toLocale("finStackMobileExt::folio.lite.success"),toLocale("finStackMobileExt::folioBackupFileSaved")+" "+data[2]+data[1])
    body: tmp[0]->body.ioReadJson.add({name: "commitButton", editorType: "button", label: toLocale("finStackExt::reportsDownload"), controlBar: true})
    body = body.map(x=> if(x->name=="okButton") x.set("label",toLocale("finStackExt::ok")) else x)
    stuff: tmp[0].set("body",body.toJSON).set("commitButton","\$commitButton").set("commitAction","").set("completeAction",[
      "window.open((finstack.pathPrefix || '')+'/finGetFile/"+context()->projName+"?fileRef=@" + recId.toStr + "');",
      ].concat(" "))

    // cleanup from folio DB if not needed
    shouldBackupInDb: data[6]
    if (not shouldBackupInDb) do
      readById(recId).diff({trash: marker()}).commit
      eval("jobRun([jobSleep(6h),folioOrphanCleanup(parseRef(\""+ recId.toStr + "\"))])")
    end
    tmp.map(x=> stuff)
  end
end


def ​

func:finFolioMenu ​

finFolioMenu() ​

Axon function


meta ​

deffunc:finFolioMenu
finStackMobileMenu✓
isfunc
liblib:finStackMobile
namefinFolioMenu
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

() => do
  sub: {
    items: [
      {
        label: toLocale("finStackMobileExt::dbLaunch"),
        icon: "icon-stack",
        tooltip: toLocale("finStackMobileExt::folioTooltip"),
        action: "app.ShowRemotePopup(null, '/pod/finFolioLiteExt/index.html', {size:{w:'90%', h:'90%'}, position:{x:'center', y:'middle'}})",
        keepOpen: true,
        classes:"tablet-only-hidden mobile-hidden"
      },

      {
        label: toLocale("finStackMobileExt::tabBarMenu"),
        icon: "icon-menu",
        tooltip: toLocale("finStackMobileExt::folioMenuTooltip"),
        action: "window.app.ObtainMenu(null, '{{targetRef}}', 'folioApp'," + finFolioSettings("forMenu2").toAxonCode +")",
        keepOpen: true
      }
    ]
  }.toJSON()

  [
    {
      displayName: toLocale("finStackMobileExt::rightMenuFolio"),
      appId: "folioApp",
      link: "",
      icon: "icon-stack",
      iconType: "class",
      ui: "html",
      minUiTarget: "phone",
      order: 201,
      action: "null",
      keepOpen: true,
      submenu: sub,
      classes: "tablet-only-hidden mobile-hidden"
    },
    {
      displayName: toLocale("finStackMobileExt::rightMenuFolio"),
      appId: "folioApp",
      link: "",
      icon: "icon-stack",
      iconType: "class",
      order: 201,
      action: "window.app.ObtainMenu(null, '{{targetRef}}', 'folioApp'," + finFolioSettings("forMenu2").toAxonCode +")",
      keepOpen: true,
      classes: "desktop2-hidden"
    }
  ].toGrid
end


def ​

func:finFolioSettings ​

finFolioSettings(stage, inp: null) ​

Axon function


meta ​

deffunc:finFolioSettings
isfunc
liblib:finStackMobile
namefinFolioSettings
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(stage, inp: null) => do
  if(stage == "forMenu2") {
    header: toLocale("finStackMobileExt::rightMenuFolio"),
    funcCall: "finFolioMenu2()",
    display: "dis",
    hideBackButton: true }

  else if(stage == "folioFileMenu") {
    header: toLocale("finStackMobileExt::folioFiles"),
    funcCall: "folioFileMenu()",
    display: "dis",
    hideBackButton: true }

  else if(stage == "folioTrashMenu") {
    header: toLocale("finStackMobileExt::folioTrash"),
    funcCall: "folioTrashMenu()",
    display: "dis",
    hideBackButton: true }

  else if(stage == "folioSnapMenu") {
    header: toLocale("finStackMobileExt::folioSnapshots"),
    funcCall: "folioSnapMenu()",
    display: "dis",
    hideBackButton: true }

  else if(stage == "folioDebugMenu") {
    header: toLocale("finStackMobileExt::folioDebug"),
    funcCall: "folioDebugMenu()",
    display: "dis",
    hideBackButton: true }

  else if(stage == "refresh") {
    displayName: toLocale("finStackExt::coreRefresh"),
    appId: "folio",
    ignoreSettings: marker(),
    action: "window.app.ObtainMenu(null, 'null','folio',"+inp.toAxonCode+")",
    icon: "icon-retweet",
    iconType: "class",
    keepOpen:true,
    order: -1009 }

  else if(stage == "empty") {
    displayName: "",
    appId: "folio",
    ignoreSettings: marker(),
    action: "null",
    keepOpen:true,
    ui: "html",
    minUiTarget: "phone",
    order: 0 }

  else if(stage == "divider") {
    displayName: "NULL",
    isDivider: true,
    appId: "folio",
    keepOpen: true,
    order: 0,
    ignoreSettings: marker() }
end


def ​

func:finFolioUploadForm ​

finFolioUploadForm(stage: null, data: null, app: null) ​

Form to upload records through file or through text, like legacy Folio Import


meta ​

appFormOnfolio
deffunc:finFolioUploadForm
distoLocale("finStackExt::upload")
folderPathtoLocale("finStackMobileExt::coreBackup")
isfunc
liblib:finStackMobile
namefinFolioUploadForm
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(stage: null, data: null, app: null) => do
  logInfo("folio_upload","stage:"+stage + " data:"+data,null)
  t: (g)=> g.toAxonCode

  if(app != null and stage != 1 and stage != 3)
  do
    if(app == "program")
      compAct: ["setTimeout(function() { " +
                    "finstack.eval('readAll(programStatus).findAll(programRec => programRec->id.readByIdPersistentTags[\"programStatus\"] != null).toRecList.map(programRec => programRec.diff({-programStatus}).commit)'); \n" +
                    "window.app.ObtainMenu(null, '{{targetRef}}','bline', "+ blineMenuSettings(null, false).toAxonCode +");" +
                  "}, 2000);"].concat()
    else if(app == "graphics")
      compAct: "setTimeout(function(){ window.app.ObtainMenu(null, '{{targetRef}}','graphicsBuilder', "+graphicsMenuSettings(false).toAxonCode +"); }, 2000);"
    else if(app == "file")
      compAct: "setTimeout(function(){ window.app.ObtainMenu(null, null,'folio',"+finFolioSettings("folioFileMenu").toAxonCode +"); }, 2000);"
    else if(app == "job")
      compAct: "setTimeout(function(){ window.app.ObtainMenu(null, null,'job',"+" {header:'"+toLocale("finStackMobileExt::rightMenuJobs")+"', funcCall:'finJobMenu2()', display:'dis'}); }, 2000);"
    else if(app == "schedule")
      compAct: "setTimeout(function(){ window.app.NavigateToApp(window.app.APP_NAMES.SCHEDULES, window.app.get('currentId')); }, 2000);"
    else if(app == "summary")
      compAct: "setTimeout(function(){ window.app.ObtainMenu(null, 'null', 'summary',"+"{header:'"+toLocale("finStackExt::summaries")+"',funcCall:'finSummaryListMenu()',display:'dis'}); }, 2000);"
    else if(app == "user")
      compAct: "setTimeout(function(){ window.app.ObtainMenu(null,"+"'null', 'users',"+ usersMainMenuSettings().toAxonCode +"); }, 2000);"
    else
      compAct: "console.log('Folio Upload Form: Unknown option: "+app+"');"
  end
  else compAct: ""

  if(stage == null)
  do
    body: [
      {name: "file", editorType: "file", fileTypes: ["zip","csv","json","trio","zinc"]},
      {name: "text", editorType: "checkbox", label: toLocale("finStackMobileExt::folioRestoreUploadText")},
      {name: "ovrt", editorType: "checkbox", label: toLocale("finStackMobileExt::folioRestoreOverwriteRecords"), defVal: true},
      {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
      {name: "commitButton", editorType: "button", label: toLocale("finStackMobileExt::licenseUploadRestart"), controlBar: true}
    ]

    {
      "dis": toLocale("finStackMobileExt::rightMenuFolio")+" "+toLocale("finStackMobileExt::licenseUploadRestart"), //"Folio Upload",
      "name": "finFolioUploadForm",
      "body": body.toJSON,
      "cancelButton": "\$cancelButton",
      "commitButton": "\$commitButton",
      "commitAction": "finFolioUploadForm(0,[\$text,\$ovrt,\$file], "+app.t+")",
      "completeAction": "if(!\$text) "+compAct,
      "finForm": marker()
    }.toGrid.addMeta({formExecute: marker()})
  end
  ////////////////////// file upload cleanup
  else if (stage == 0)
  do
    txt:   try data[0] catch false
    ovrt:  try data[1] catch false
    fid:   try data[2] catch null
    out: null
    try do
      out = if(txt) finFolioUploadForm(2, ovrt, app) else finFolioUploadForm(1, [fid], ovrt)
      if(fid != null and fid != "") do
        readById(fid).finHardDelete()
      end
      out
    end
    catch(e) do
      if(fid != null and fid != "") readById(fid).finHardDelete()
      finFormAlertOk(toLocale("finStackMobileExt::folio.lite.error"),toLocale("finStackMobileExt::folioRestoreUploadError"))
        .map(x=> x.set("body", x->body.ioReadJson.map(y=> if(y->name=="okButton") y.set("label",toLocale("finStackExt::ok")) else y).toJSON))
    end
  end
  ////////////////////// auto upload
  else if(stage == 1)
  do
    if(data.size > 0 and data[0] != "")
    do
      id: data[0]
      keepIds: app==true
      logInfo("folio_upload","id:"+id + " keepIds:" + keepIds)
      file: readById(id)
      type: file->dis.split(".")[-1].lower

      if(type == "zip") finRestoreRecord(file->id,{returnedImported:false},keepIds)
      else
      do
        if(type == "csv") data = ioReadCsv(ioBin(file->id, "file"))
        else if(type == "json") data = ioReadJsonGrid(ioBin(file->id, "file"))
        else if(type == "trio") data = ioReadTrio(ioBin(file->id, "file"))
        else if(type == "zinc") data = ioReadZinc(ioBin(file->id, "file"))

        data.toGrid.removeCol("id").each x=>
        do
          if(x.has("origId")) do
            if(x->origId.isStr) x = x.set("origId", x->origId.split(" ")[0][1..-1].parseRef)
            if(app) finHardDelete(readAll(id==x->origId))
          end

          x.names.each prop =>
          do
            if(finIsTagBlackList(prop))
              x = x.remove(prop)
          end

          diff(null,{}.merge(x),{add}).commit
        end
      end

      cou: 0

      readAll(origId).each x=>
      do
        try x.diff({-origId}).commit catch cou = cou + 1
      end

      if(type != "zip") finFormAlertOk(toLocale("finStackMobileExt::folioRestoreFinished"), toLocale("finStackMobileExt::folioRestoreUploaded").replace("{0}",data.size.toStr).replace("{1}",cou.toStr)).map(x=> x.set("body", x->body.ioReadJson.map(y=> if(y->name=="okButton") y.set("label",toLocale("finStackExt::ok")) else y).toJSON))
      else finFormAlertOk(toLocale("finStackMobileExt::folioRestoreFinished"), toLocale("finStackMobileExt::folioRestoreFinUpl").replace("{0}",cou.toStr)).map(x=> x.set("body", x->body.ioReadJson.map(y=> if(y->name=="okButton") y.set("label",toLocale("finStackExt::ok")) else y).toJSON))
    end
    else finFormAlertOk(toLocale("finStackMobileExt::folio.lite.error"),toLocale("finStackExt::folioRestoreNoFile")).map(x=> x.set("body", x->body.ioReadJson.map(y=> if(y->name=="okButton") y.set("label",toLocale("finStackExt::ok")) else y).toJSON))
  end
  ////////////////////// paste text
  else if(stage == 2)
  do
    ftypes: [
      {a:"Trio",b:"trio"},
      {a:"Zinc",b:"zinc"},
      {a:"JSON",b:"json"},
      {a:"CSV (" + toLocale("finStackMobileExt::refTagsMayBeBroken") + ")",b:"csv"}
    ].toAxonCode

    body: [
      {name: "text", editorType: "textarea", prompt: toLocale("finStackMobileExt::folioRestorePaste"), defVal: "", height: 200},
      {name: "type", editorType: "combobox", prompt: toLocale("finStackMobileExt::folioMenuFormat"), dataProvider: ftypes, labelField: "a", selectedValueTags: "b", defIndex: 0},
      {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
      {name: "commitButton", editorType: "button", label: toLocale("finStackExt::coreApply"), controlBar: true}
    ]

    {
      "dis": toLocale("finStackMobileExt::rightMenuFolio")+" "+toLocale("finStackMobileExt::licenseUploadRestart"), //"Folio Upload",
      "name": "finFolioUploadForm2",
      "body": body.toJSON,
      "cancelButton": "\$cancelButton",
      "commitButton": "\$commitButton",
      "commitAction": "finFolioUploadForm(3,[\$text,\$type],"+data+")",
      "completeAction": compAct,
      "finForm": marker()
    }.toGrid.addMeta({formExecute: marker()})
  end
  ////////////////////// upload text
  else if(stage == 3)
  do
    if(data[0].trim != "")
    do
      if(data[1] == "csv") data = ioReadCsv(data[0].trim)
      else if(data[1] == "json") data = ioReadJsonGrid(data[0].trim)
      else if(data[1] == "trio") data = ioReadTrio(data[0].trim)
      else if(data[1] == "zinc") data = ioReadZinc(data[0].trim)

      data.toGrid.removeCol("id").each x=>
      do
        if(x.has("origId"))
        do
          if(x->origId.isStr) x = x.set("origId", x->origId.split(" ")[0][1..-1].parseRef)
          if(app) finHardDelete(readAll(id==x->origId))
        end

        x.names.each prop =>
        do
          if(finIsTagBlackList(prop))
            x = x.remove(prop)
        end

        diff(null,{}.merge(x),{add}).commit
      end

      cou: 0

      readAll(origId).each x=>
      do
        try x.diff({-origId}).commit catch cou = cou + 1
      end

      finFormAlertOk(toLocale("finStackMobileExt::folioRestoreFinished"),toLocale("finStackMobileExt::folioRestoreUploaded").replace("{0}",data.size.toStr).replace("{1}",cou.toStr)).map(x=> x.set("body", x->body.ioReadJson.map(y=> if(y->name=="okButton") y.set("label",toLocale("finStackExt::ok")) else y).toJSON))
    end
    else finFormAlertOk(toLocale("finStackExt::regError"),toLocale("finStackMobileExt::folioRestoreNoText")).map(x=> x.set("body", x->body.ioReadJson.map(y=> if(y->name=="okButton") y.set("label",toLocale("finStackExt::ok")) else y).toJSON))
  end
end


def ​

func:finFormAddEditHaystackConnector ​

finFormAddEditHaystackConnector(haystackConnRef: null, refill: null, folderPath: null) ​

Axon function


meta ​

deffunc:finFormAddEditHaystackConnector
isfunc
liblib:finStackMobile
namefinFormAddEditHaystackConnector
overridable✓
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(haystackConnRef: null, refill: null, folderPath: null) => do
  if(folderPath.isDict)
  do
    if (foilderPath["emptyFolder"] == null)
    do
      if (folderPath["treePath"] != null)
        folderPath = folderPath->treePath
      else folderPath = folderPath["folderPath"]
    end
    else
      folderPath = folderPath["id"]
  end

  action: "if((\$usernameInput).isEmpty or (\$uriInput).isEmpty or (\$displayNameInput).isEmpty) " + //(\$passwordInput).isEmpty or
    "finFormAddEditHaystackConnector(null, {uri: \$uriInput, dis: \$displayNameInput, haystackSlot: \$haystackSlotRadio, equipFilter: \$equipFilterInput, pointFilter: \$pointFilterInput, username: \$usernameInput, passwordEmpty: (\$passwordInput).isEmpty}, "+folderPath.toAxonCode+") " +
    "else finAddEditHaystackConnectorCommit(null, {uri: \$uriInput, dis: \$displayNameInput, haystackSlot: \$haystackSlotRadio, equipFilter: \$equipFilterInput, pointFilter: \$pointFilterInput, username: \$usernameInput, password: \$passwordInput, folderPath: "+folderPath.toAxonCode+"})"

  uriDef: "http://host/haystack/"
  disDef: "Haystack Conn"
  slotDef: "No"
  equipDef: ""
  pointDef: ""
  userDef: ""
  changePassDef: false
  formTitle: if (haystackConnRef == null) toLocale("finStackMobileExt::addHaystackConn") else toLocale("finStackMobileExt::editHaystackConn")
  commitButtonStr: if (haystackConnRef == null) toLocale("finStackExt::add") else toLocale("finStackExt::coreApply")

  haystackSlotRadios: [
    {name: "haystackSlotRadio", editorType: "radio", label: toLocale("finStackExt::yes"), group: "haystackSlot", selectedValue: true, encapsulate: false},
    {name: "haystackSlotRadio", editorType: "radio", label: toLocale("finStackExt::no"), group: "haystackSlot", selectedValue: false, encapsulate: false}
  ]

  treeRefresh: "window.app.RefreshBuilderTreeNodeForId('@folderPath:haystackConn:');"

  if(folderPath != null)
  do
    folder: try readById(folderPath.replace("@", "").parseRef, false) catch null

    if(folder != null)
      //treeRefresh = "window.app.RefreshBuilderTreeNodeForId('@folderPath:haystackConn:"+folder->folderPath+folder->dis+"')"
      treeRefresh = treeRefresh + " setTimeout(function(){ window.app.RefreshBuilderTreeNodeForId('@folderPath:haystackConn:"+folder->folderPath+folder->dis+"'); }, 1250);"
    else
    do
      fixedFolderPath: folderPath.replace("/", "--").replace(" ", "__").replace("\"", "-QUOTE-")
      treeRefresh = "window.app.RefreshBuilderTreeNodeForId('@folderPath:haystackConn:"+fixedFolderPath+"')"
     // treeRefresh = treeRefresh + " setTimeout(function(){ window.app.RefreshBuilderTreeNodeForId('"+folderPath+"'); }, 1250);"
    end
  end

  if(readCount(haystackConn or haystackConnFolder) == 0)
    treeRefresh = "window.app.RefreshBuilderTreeNodeForId('@folderPath:connectors:'); setTimeout(function(){ "+treeRefresh+" }, 1250);"

  if(refill != null) do
    uriDef = refill->uri
    disDef = refill->dis
    equipDef = refill->equipFilter
    pointDef = refill->pointFilter
    userDef = refill->username

    if(refill->haystackSlot) slotDef = "Yes"
    if(refill.has("changePassword")) changePassDef = refill->changePassword

    if (haystackConnRef != null)
      action = "if((\$usernameInput).isEmpty or (\$uriInput).isEmpty or (\$displayNameInput).isEmpty) " +
        "finFormAddEditHaystackConnector("+haystackConnRef.toAxonCode+", {uri: \$uriInput, dis: \$displayNameInput, haystackSlot: \$haystackSlotRadio, equipFilter: \$equipFilterInput, pointFilter: \$pointFilterInput, username: \$usernameInput, changePassword: \$changePasswordCheck}) " +
        "else if(\$changePasswordCheck) finFormNewHaystackPassword("+haystackConnRef.toAxonCode+", {uri: \$uriInput, dis: \$displayNameInput, haystackSlot: \$haystackSlotRadio, equipFilter: \$equipFilterInput, pointFilter: \$pointFilterInput, username: \$usernameInput, changePassword: \$changePasswordCheck}) " +
        "else finAddEditHaystackConnectorCommit("+haystackConnRef.toAxonCode+", {uri: \$uriInput, dis: \$displayNameInput, haystackSlot: \$haystackSlotRadio, equipFilter: \$equipFilterInput, pointFilter: \$pointFilterInput, username: \$usernameInput})"
  end
  else if(haystackConnRef != null) do
    haystackConn: readById(haystackConnRef)

    uriDef = haystackConn->uri
    disDef = haystackConn->dis
    equipDef = haystackConn->equipFilter
    pointDef = haystackConn->pointFilter
    userDef = haystackConn->username

    if(haystackConn->haystackSlot) slotDef = "Yes"

    action = "if((\$usernameInput).isEmpty or (\$uriInput).isEmpty or (\$displayNameInput).isEmpty) " +
      "finFormAddEditHaystackConnector("+haystackConnRef.toAxonCode+", {uri: \$uriInput, dis: \$displayNameInput, haystackSlot: \$haystackSlotRadio, equipFilter: \$equipFilterInput, pointFilter: \$pointFilterInput, username: \$usernameInput, changePassword: \$changePasswordCheck}) " +
      "else if(\$changePasswordCheck) finFormNewHaystackPassword("+haystackConnRef.toAxonCode+", {uri: \$uriInput, dis: \$displayNameInput, haystackSlot: \$haystackSlotRadio, equipFilter: \$equipFilterInput, pointFilter: \$pointFilterInput, username: \$usernameInput, changePassword: \$changePasswordCheck}) " +
      "else finAddEditHaystackConnectorCommit("+haystackConnRef.toAxonCode+", {uri: \$uriInput, dis: \$displayNameInput, haystackSlot: \$haystackSlotRadio, equipFilter: \$equipFilterInput, pointFilter: \$pointFilterInput, username: \$usernameInput})"
  end

  haystackSlotRadios = haystackSlotRadios.map(r => if(r->label == slotDef) r.set("defVal", true) else r)

  body: [
    {
      name: "uriInput",
      editorType: "textinput",
      prompt: toLocale("finStackExt::folioFilesURI") + ":",
      defVal: uriDef
    },

    {
      name: "displayNameInput",
      editorType: "textinput",
      prompt: toLocale("finStackMobileExt::hostDisplayName") + ":",
      defVal: disDef
    },

    {
      name: "haystackSlotGroup",
      editorType: "group",
      horizontal,
      children: [
        {name: "haystackSlotLabel", editorType: "label", text: toLocale("finStackMobileExt::haystackSlot"), width: 350}
      ].addAll(haystackSlotRadios)
    },

    {
      name: "equipFilterInput",
      editorType: "textinput",
      prompt: toLocale("j2FinToolsExt::equipFilter") + ":",
      defVal: equipDef
    },

    {
      name: "pointFilterInput",
      editorType: "textinput",
      prompt: toLocale("finStackExt::pointFilter") + ":",
      defVal: pointDef
    },

    {
      name: "usernameInput",
      editorType: "textinput",
      prompt: toLocale("finStackExt::settingsMenuUsername") + ":",
      defVal: userDef
    },

    {
      name: "passwordInput",
      editorType: "textinput",
      prompt: toLocale("finStackExt::settingsMenuPassword") + ":",
      password: true
    },

    {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
    {name: "applyButton", editorType: "button", label: commitButtonStr, controlBar: true}
  ]

  if(haystackConnRef != null) do
    body = body.remove(6).insert(6, {
      name: "changePasswordCheck",
      editorType: "checkbox",
      label: toLocale("finStackMobileExt::changePassword"),
      defVal: changePassDef
    })
  end

  if(refill != null) do
    if(haystackConnRef == null and refill->passwordEmpty)
      body = body.insert(0, {
        name: "noPassMsg",
        editorType: "label",
        text: toLocale("finStackMobileExt::enterAPassword")
      })

    if(refill->username.isEmpty)
      body = body.insert(0, {
        name: "noUsernameMsg",
        editorType: "label",
        text: toLocale("finStackMobileExt::enterAUsername")
      })

    if(refill->dis.isEmpty)
      body = body.insert(0, {
        name: "noDisMsg",
        editorType: "label",
        text: toLocale("finStackMobileExt::enterADisplayName")
      })

    if(refill->uri.isEmpty)
      body = body.insert(0, {
        name: "noUriMsg",
        editorType: "label",
        text: toLocale("finStackMobileExt::enterAUri")
      })
  end

  { "dis": formTitle,
    "name": "finFormAddEditHaystackConnector" + (if(refill != null) random(1..1000) else ""),
    "body": body.toJSON,
    "cancelButton": "\$cancelButton",
    "commitButton": "\$applyButton",
    "commitAction": action,
    "completeAction": "window.app.RefreshBuilderGridAt(0, 'panel'); " +treeRefresh,
    "finForm": marker()
  }.toGrid.addMeta({formExecute: marker()})
end


def ​

func:finFormBacnetConnDiscoverSettings ​

finFormBacnetConnDiscoverSettings(refill: null) ​

Axon function


meta ​

deffunc:finFormBacnetConnDiscoverSettings
isfunc
liblib:finStackMobile
namefinFormBacnetConnDiscoverSettings
overridable✓
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(refill: null) => do
  curSettings: read(bacnetDiscoverSettings, false)
  recId:  null
  makeRec: false
  broadCastList: bacnetListBroadcastIps().addRow({ip: "255.255.255.255"}) //[{ip: "Custom Broadcast Address"}].toGrid.addRows(
  localBindAddress:bacnetGetLocalBindAddress()
  bacnetMstp: read(ext == "bacnetMstp", false)

  if(curSettings == null) do
    makeRec = true
    curSettings = finGetDiscoveryConfiguration("bacnet").gridRowsToDict((row, index) => row->name, (row, index) => row->defaultValue)
  end else do
    recId = curSettings->id
    if(not broadCastList.colToList("ip").contains(curSettings->broadcastAddress)) broadCastList = broadCastList.addRow({ip: curSettings->broadcastAddress})
  end

  //defVals
  newCommit: "finSetBacnetDiscoverCommit({bacnetDiscoverSettings, customLocal: null, customBroad: \$customBroadcast, broadcastAddress: \$broadcastAdd, localAddress: \$localAdd, instanceLow: \$instanceStart, instanceHi: \$instanceEnd, networkNo: \$network, discoveryTimeout: parseNumber(\$timeout + \"sec\")}, null)"
  updateCommit:"finSetBacnetDiscoverCommit({customLocal: null, customBroad: \$customBroadcast, broadcastAddress: \$broadcastAdd, localAddress: \$localAdd, instanceLow: \$instanceStart, instanceHi: \$instanceEnd, networkNo: \$network, discoveryTimeout: parseNumber(\$timeout + \"sec\")}, "+recId.toAxonCode+")"

  if(refill == null) do
    broad: broadCastList.colToList("ip").index(curSettings->broadcastAddress)
    local: localBindAddress
    start: curSettings->instanceLow
    ending: curSettings->instanceHi
    net: curSettings->networkNo
    timeout: curSettings->discoveryTimeout
    baudDef: curSettings["baudRate"]
    portDef: curSettings["serialPort"]
    customBroadDef: ""
  end else do
    curSettings = refill

    broad: broadCastList.colToList("ip").index(curSettings->broadcastAddress)
    local: localBindAddress
    start: curSettings->instanceLow
    ending: curSettings->instanceHi
    net: curSettings->networkNo
    timeout: curSettings->discoveryTimeout
    baudDef: curSettings["baudRate"]
    portDef: curSettings["serialPort"]
    customBroadDef: curSettings->customBroad
  end

  body: [
    {
      name: "broadcastAdd",
      editorType: "combobox",
      prompt: toLocale("finStackMobileExt::broadcastAddress") + ":",
      dataProvider: broadCastList.toRecList.toAxonCode,
      labelField: "ip",
      selectedValueTags: "ip",
      defIndex: broad
    },

    {
      name: "customBroadcast",
      editorType: "textinput",
      prompt: toLocale("finStackMobileExt::customBroadcastAddress") + ":",
      defVal: customBroadDef
    },

    {
      name: "localAdd",
      editorType: "label",
      prompt: toLocale("finStackMobileExt::localAddress") + ":",
      text: localBindAddress
    },

    {
      name: "instanceStart",
      editorType: "numericstepper",
      prompt: toLocale("finStackMobileExt::instanceNumberStart") + ":",
      minVal: 0,
      maxVal: 4194303,
      defVal: start
    },

    {
      name: "instanceEnd",
      editorType: "numericstepper",
      prompt: toLocale("finStackMobileExt::instanceNumberEnd") + ":",
      minVal: 0,
      maxVal: 4194303,
      defVal: ending
    },

    {
      name: "network",
      editorType: "numericstepper",
      prompt: toLocale("finStackMobileExt::networkNumber") + ":",
      minVal: 0,
      maxVal: 65535,
      defVal: net
    },

    {
      name: "timeout",
      editorType: "numericstepper",
      prompt: toLocale("finStackMobileExt::timeoutSeconds") + ":",
      minVal: 0,
      defVal: timeout
    },

    {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
    {name: "applyButton", editorType: "button", label: toLocale("finStackExt::coreApply"), controlBar: true}
  ]

  if(bacnetMstp != null) do
    body = body.insertAll(0, [
      {
        name: "serialPort",
        editorType: "textinput",
        prompt: toLocale("finStackMobileExt::serialPort") + ":",
        defVal: if(portDef == null) "" else portDef
      },

      {
        name: "baud",
        editorType: "numericstepper",
        prompt: toLocale("finStackMobileExt::baudRate") + ":",
        minVal: 0,
        maxVal:4294967295,
        defVal: if(baudDef == null) "76800" else baudDef
      }
    ])

    newCommit = newCommit.replace("bacnetDiscoverSettings", "bacnetDiscoverSettings, baudRate: \$baud, serialPort: \$serialPort")
    updateCommit = updateCommit.replace("({", "({baudRate: \$baud, serialPort: \$serialPort,")
  end

  if(refill != null)
    body = body.insert(0, {name: "errMsg", editorType: "label", text: refill->errMsg})

  { "dis": toLocale("finStackMobileExt::deviceDiscoverySettings"),
    "name": "finFormBacnetConnDiscoverSettings" + (if(refill != null) random(0..1000)) ,
    "body": body.toJSON,
    "cancelButton": "\$cancelButton",
    "commitButton": "\$applyButton",
    "commitAction": if(makeRec) newCommit else updateCommit,
    "finForm": marker()
  }.toGrid.addMeta({formExecute: marker()})
end


def ​

func:finFormCloneConnector ​

finFormCloneConnector(selectedTargets, curType: "bacnet", curContext: null, reopen: false, jsAction: "") ​

Axon function


meta ​

deffunc:finFormCloneConnector
isfunc
liblib:finStackMobile
namefinFormCloneConnector
overridable✓
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(selectedTargets, curType: "bacnet", curContext: null, reopen: false, jsAction: "") => do
  defTempIndex: 0
  defUrlIndex: 0
  defParentIndex: 0
  connIds: []
  haystackDevices: []
  possibleRefs: null
  runJs: ""

  navType: "topLevel"
  navTypeParent: ""
  navTree: read(navMeta)->equipPath.split("/").map(r => reFind(r"[a-zA-Z_0-9]+", r))

  targetEquip: null
  connList: readAll(parseFilter(curType+"Conn")).sort("dis")

  runJs = jsAction.replace(curContext.toStr, "@'+\$equipTemplate."+navTree[navTree.index("equip") - 1]+"Ref+'")

  //handle Haystackconn (they come in as a dict)
  if(selectedTargets.isDict)
  do
    connIds = connIds.add(selectedTargets->connRef)
    haystackDevices = selectedTargets->selectedItems
  end
  else //all other connector types
    connIds = selectedTargets

  // not topLevel
  if(targetEquip != null)
  do
    navType = targetEquip.finNavMetaWhoAmI()            // find out the location type (like equip)
    navTypeParent = navTree[navTree.index(navType) - 1] // find out the parent of our current location (if equip then floor)

    //find all connRefs under out current location
    try possibleRefs = readAll(parseFilter("point and "+curType+"ConnRef and "+targetEquip.finNavMetaWhoAmI()+"Ref == "+targetEquip->id.toAxonCode)).unique(curType+"ConnRef")
    catch possibleRefs = []

    /*---find def connector---*/
    if(possibleRefs.isEmpty()) //nothing was found
      possibleRefs = null
    else if(possibleRefs.size == 1) //only one connectorRef was found
      possibleRefs = possibleRefs[0][curType+"ConnRef"]
    else // multiple connectorRefs found
    do
      // find the connector with the most points
      possibleRefs = possibleRefs.sort((a,b) => do
        aFilter: "point and "+curType+"ConnRef == "+a[curType+"ConnRef"].toAxonCode+" and "+targetEquip.finNavMetaWhoAmI()+"Ref == "+targetEquip->id.toAxonCode
        bFilter: "point and "+curType+"ConnRef == "+a[curType+"ConnRef"].toAxonCode+" and "+targetEquip.finNavMetaWhoAmI()+"Ref == "+targetEquip->id.toAxonCode
        readCount(parseFilter(aFilter)) <=> readCount(parseFilter(bFilter))
      end)[0][curType+"ConnRef"]
    end

    // find the default index for the base url among the list of connectors (should be regulated to 1 conn type)
    if(possibleRefs != null and haystackDevices.isEmpty) defUrlIndex = connList.colToList("id").index(possibleRefs)

    // no specific was found, so add a "blank" selection to the front of the list of conns
    else connList = [{dis: toLocale("finStackMobileExt::selectGenericConnector").replace("{connType}", curType.capitalize), id: "null"}].toGrid.addRows(connList)

    // find def parent or def equip
    if(navType != "equip")
      defParentIndex = readAll(parseFilter(navType + (if(navTypeParent != "" and navTypeParent != null) " and " + navTypeParent + "Ref == " + targetEquip[navTypeParent+"Ref"].toAxonCode else ""))).map(r => r.merge({dis: r.dis})).sort("dis").colToList("id").index(curContext)
    else
      defTempIndex = readAll(parseFilter("equip and "+navTypeParent+"Ref == "+targetEquip[navTypeParent+"Ref"].toAxonCode)).sort("navName").colToList("id").index(curContext)
  end

  //haystack specific
  if(not haystackDevices.isEmpty)
  do
    connList = "finGetHaystackCurPaths("+selectedTargets->connRef.toAxonCode+", readById((\$equipTemplate)->id.parseRef, false))"
    defUrlIndex = 1
  end //end haystack

  // create body of form
  body: [
    {
      name: "parentCombo",
      editorType: "combobox",
      prompt: toLocale("finStackMobileExt::showEquipFrom"),
      dataProvider: "readAll("+navTree[1]+").sort(\"dis\")",
      labelField: "dis",
      selectedValueTags: "id",
      defIndex: defParentIndex
    },

    {
      name: "equipTemplate",
      editorType: "combobox",
      prompt:toLocale("finStackMobileExt::equipForTemplate"),
      dataProvider: "readAll(equip and "+navTree[1]+"Ref == \$parentCombo).map(r => r.merge({dis: r.dis, id:r->id.toStr, "+navTree[navTree.index("equip") - 1]+"Ref: r->"+navTree[navTree.index("equip") - 1]+"Ref.toStr})).sort(\"dis\")",
      labelField: "dis",
      selectedValueTags: "id, "+ navTree[navTree.index("equip") - 1]+"Ref",
      defIndex: defTempIndex
    },

    {
      name: "baseUrl",
      editorType: "combobox",
      prompt: toLocale("finStackMobileExt::baseUrl"),
      dataProvider: if(connList.isStr) connList else connList.toRecList.toAxonCode,
      labelField: "dis", //if(haystackDevices.isEmpty) "dis" else "id",
      selectedValueTags: "id",
      defIndex: defUrlIndex
    },

    { name: "tagetDiv", editorType:"separator", label: toLocale("finStackMobileExt::targets")},
    {
      name: "targetTable",
      editorType: "table", //selectedTargets below
      dataProvider: if(haystackDevices.isEmpty) "readByIds("+connIds.toAxonCode+").toRecList.map(r => {host: try r->uri.uriHost catch \"\", name: r->dis})"
                    else "("+haystackDevices.toAxonCode+").map(r => {relativeUrl: r, name: r.toStr.split(\".\")[-1]})",
      height: 200
    },

    { name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true },
    { name: "applyButton", editorType: "button", label: toLocale("finStackExt::coreCreate"), controlBar: true }
  ]

  // manipulate form body if needed
  if(targetEquip != null and navType == "equip")
  do
    body = body[1..-1].map(r => do
      if(r->name == "equipTemplate")
        r.merge({
          dataProvider:"readAll(equip and "+navTypeParent+"Ref == "+targetEquip[navTypeParent+"Ref"].toAxonCode+").map(r => r.merge({id:r->id.toStr, "+navTree[navTree.index("equip") - 1]+"Ref: r->"+navTree[navTree.index("equip") - 1]+"Ref.toStr})).sort(\"navName\")",
          labelField: "navName"
        })
      else
        r
    end) // end map
  end
  else if(targetEquip != null)
  do
    body = body.map(r => do
      if(r->name == "parentCombo") r.merge({dataProvider: "readAll("+navType+(if(navTypeParent != "" and navTypeParent != null) " and " + navTypeParent + "Ref == " + targetEquip[navTypeParent+"Ref"].toAxonCode else "")+").map(r => r.merge({dis: r.dis})).sort(\"dis\")"})
      else if(r->name == "equipTemplate") r.merge({dataProvider: "readAll(equip and " + navType + "Ref == \$parentCombo).map(r => r.merge({dis: r.dis, id:r->id.toStr, "+navTree[navTree.index("equip") - 1]+"Ref: r->"+navTree[navTree.index("equip") - 1]+"Ref.toStr})).sort(\"dis\")"})
      else r
    end) // end map
  end

  // add error message if needed
  if(reopen)
    body = body.insert(0, {
      name:"errMsg",
      editorType:"label",
      text:toLocale("finStackMobileExt::selectGenericConnectorToClone").replace("{connType}", curType)
    })

  return {
    "dis": toLocale("finStackMobileExt::cloneOpts"),
    "name": "finFormCloneConnector" + (if(reopen) random(1..10000) else ""),
    "body": body.toJSON,
    "cancelButton": "\$cancelButton",
    "commitButton": "\$applyButton",
    "commitAction": "if((() => \$equipTemplate->id)() == \"null\") finFormCloneConnector("+selectedTargets.toAxonCode+", "+curType.toAxonCode+", "+curContext.toAxonCode+", true, "+jsAction.toAxonCode+")" +
                    "else finCloneConnectorCommit((\$equipTemplate)->id.parseRef, \$baseUrl, "+(if(haystackDevices.isEmpty) connIds.map(r => {name: r->dis, connRef: r->id, objectPath: "null"}).toAxonCode else haystackDevices.map(r => {name: r.toStr.split(".")[-1].decodeHaystack, objectPath: r.toAxonCode, connRef: connIds[0]}).toAxonCode)+")",
    "completeAction": runJs,
    "finForm": marker()
  }.toGrid.addMeta({formExecute: marker()})
end


def ​

func:finFormConfirmChangesAlert ​

finFormConfirmChangesAlert(action, msg, jsAction: "") ​

Creates a basic form with "Warning" as the form title, a "Cancel" button, and an "Apply" button.

action - A string containing Axon code to run when "Apply" is clicked.

msg - The message to display on the form. Will be a label.


meta ​

constructfinFormConfirmChangesAlert("readAll(site)", "Read all si...
deffunc:finFormConfirmChangesAlert
isfunc
liblib:finStackMobile
namefinFormConfirmChangesAlert
overridable✓
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(action, msg, jsAction: "") => do
  showButtons: true
  body: []

  if(msg.isList and msg.findAll(v => v.isDict and v.has("changing")).size == 0)
    showButtons = false

  if(showButtons)
    body = [
      { name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true },
      { name: "applyButton", editorType: "button", label: toLocale("finStackExt::coreApply"), controlBar: true }
    ]
  else
    body = [{ name: "cancelButton", editorType: "button", label: toLocale("finStackExt::ok"), controlBar: true }]

  if(not msg.isList)
  body = body.add({ name: "msgLabel", editorType: "label", text: msg })
  else
    each(msg) (x, i) =>
    do
      if(x.isStr)
        body = body.add({ name: i+"msgLabel", editorType: "label", text: x})
      else if(x.isDict)
        body = body.add({name: i+"txtArea", editorType: "textarea", defVal: "   \u25AA "+ x->nameList.concat("\n   \u25AA "), editable: false, height: if(x->nameList.size > 6) 125 else x->nameList.size * 20})
    end

  { "dis": toLocale("finStackExt::warning"),
    "name": "finFormConfirmChangesAlert",
    "body": body.toJSON,
    "cancelButton": "\$cancelButton",
    "commitButton": "\$applyButton",
    "commitAction": action,
    "completeAction": jsAction,
    "finForm": marker()
  }.toGrid.addMeta({formExecute: marker()})
end


def ​

func:finFormDBAddEdit ​

finFormDBAddEdit(treeType, edit: null, refill: null, folderPath: null, refreshTop: false, haystackRef: null, isConn: false) ​

A form used to create or edit DB Builder items.

treeType - <string> The type of tree this form is being opened from. Should match the value of treeTagName of the appropriate tree when running finNavTreeTypes(true).

edit - <dict> Will be a dict with the id and dis of the item to be edited. A value of null indicates a new item. Default is null

refill - <dict> Will be a dict containing the information entered by the user in a previous instance of this form. Only used when invalid user input is present. Default is null.

folderPath - <string> If editing, the folderPath of the selected item. If creating a new item, this will be the folder path in which the new item is placed. Default is null.

Currently only implemented for tag bundle and save filter items.

Constructs a form to either create a new item or edit an existing item. If editing, basic fields should appear populated with the item's current value(s).


meta ​

deffunc:finFormDBAddEdit
isfunc
liblib:finStackMobile
namefinFormDBAddEdit
overridable✓
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(treeType, edit: null, refill: null, folderPath: null, refreshTop: false, haystackRef: null, isConn: false) => do
  curItem: null

  //check if valid item to edit
  if(edit != null) do
    if(edit.isList) edit = edit[0]

    if(edit["id"] != null) curItem = readById(edit->id, false)
    else curItem = null
  end

  //if a new item or a valid item was selected to edit
  if(treeType == "schedule") do
    return scheduleCreateNewForm(null, false, null, "")
  end
  if(treeType == "job") do
    return jobCreateForm((if(curItem == null) curItem else curItem->id), null, folderPath, true)
  end
  else if (treeType == "connTuning")
  do
    return finFormCreateTuningPolicy((if(curItem == null) curItem else curItem->id), folderPath, refreshTop)
  end
  else if(edit == null or curItem != null)
  do
    temp: generateFormRefreshCalls(treeType, folderPath, refreshTop, true)

    action: ""
    title: ""
    nameDef: ""
    filterDef: ""
    dictStr: ""
    defaultFolderPath: temp->defaultFolderPath
    jsAction: temp->jsAction
    isEmptyFolder: temp->isEmptyFolder

    //make form body with buttons
    body: [
      {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
      {name: "applyButton", editorType: "button", label: if(edit == null) toLocale("finStackExt::add") else toLocale("finStackExt::save"), controlBar: true}
    ]

    //consider using func(name)? this finds funcs even with nodoc
    //tag it with treeType + "Tree" and addEdit
    addEditData: funcs(parseFilter(treeType+"Tree and dbAddEdit"))

    if (not addEditData.isEmpty() or isConn)
    do
      if(not addEditData.isEmpty())
        addEditData = eval(addEditData[0]->name+"("+(if (refill != null) refill.merge({isRefill}).toAxonCode else curItem.toAxonCode)+", "+folderPath.toAxonCode+")")
      else
        addEditData = finDbGenericConnectorsAddEdit((if (refill != null) refill.merge({isRefill}) else curItem), folderPath, treeType)

      body = body.addAll(addEditData->body)
      title = addEditData->title

      if (curItem != null)
        defaultFolderPath = try reFind(r"[^/].*", curItem["folderPath"]) catch ""

      dictStr = addEditData->dictAsStr
      refillDictStr: addEditData["refillDictAsStr"]

      //special case for modbus conn
      if (treeType == "modbusConn")
      do
        regUriIndex: body.toGrid.colToList("name").index("modbusRegMapUriInput")
        regUriField: body[regUriIndex].merge({"prompt": toLocale("finStackMobileExt::modbusForm.modbusRegMapUri")})

        if (curItem == null or not curItem.has("modbusRegMapUri"))
           regUriField = body[regUriIndex].merge({"defVal": `data/modbus/xxx.csv`})

        body = body.remove(regUriIndex).map(item => do
          if (item.has("prompt"))
            return item.set("prompt", toLocale("finStackMobileExt::modbusForm." + item["prompt"].toTagName))

          return item
        end).insertAll(regUriIndex + 1, [
          {
            name: "modbusRegMapUriCombo",
            editorType: "combobox",
            prompt: toLocale("finStackMobileExt::existingRegMapPrompt"),
            dataProvider: "[{name: toLocale(\"finStackMobileExt::omMenuAddNewTitle\"), uri: \"null\"}].toGrid.addRows(modbusRegMapList())",
            labelField: "name",
            selectedValueTags: "uri",
            defIndex: 0
          },

          {name:"label", editorType: "label", text: toLocale("finStackMobileExt::filterEditor.Or")},

          regUriField
        ])

        dictStr = dictStr.replace("modbusRegMapUri:", "modbusRegMapUri: if (\$modbusRegMapUriCombo != \"null\") (\$modbusRegMapUriCombo).parseUri else ")
      end

      if (not dictStr.isEmpty())
      do
        if (not dictStr.startsWith("{")) dictStr = "{"+dictStr
        if (not dictStr.endsWith("}")) dictStr = dictStr+"}"
      end

      if (refillDictStr != null and not refillDictStr.isEmpty())
      do
        if (not refillDictStr.startsWith("{")) refillDictStr = "{"+refillDictStr
        if (not refillDictStr.endsWith("}")) refillDictStr = refillDictStr+"}"
      end
      else
        refillDictStr = dictStr

      action = "if (not ("+addEditData->validation+")) finFormDBAddEdit("+treeType.toAxonCode+","+edit.toAxonCode+", "+refillDictStr+", "+folderPath.toAxonCode+","+refreshTop.toAxonCode+","+haystackRef.toAxonCode+","+isConn.toAxonCode+") "+
              "else dbAddEditCommit("+(if (edit == null) "null" else edit->id.toAxonCode )+", "+dictStr+", "+defaultFolderPath.toAxonCode+")"

      if (addEditData["completeAction"] != null) jsAction = addEditData->completeAction
      else jsAction = jsAction + " window.app.RefreshBuilderGridAt(0, 'panel');"

      // special haystack case:
      if (haystackRef != null)
      do
        jsAction = jsAction.replace("@folderPath", "@folderPath:" + haystackRef)
        dictStr = dictStr.replace("savedQueryFilter", "haystackSavedQueryFilter, haystackConnRef: "+haystackRef.toAxonCode)
        action = action.replace("@folderPath", "@folderPath:" + haystackRef)
      end
    end

    //if destination was an empty folder, modify action string to include it's id as last parameter
    if(isEmptyFolder and edit == null) action = action[0..-2] + ", " + folderPath + ")"

    return {
      "dis": title,
      "name": if(refill == null) "finFormDBAddEdit" else "finFormDBAddEdit" + random(1..1000),
      "body": body.toJSON,
      "cancelButton": "\$cancelButton",
      "commitButton": "\$applyButton",
      "commitAction": action,
      "completeAction": jsAction,
      "finForm": marker()
    }.toGrid.addMeta({formExecute: marker()})
  end else
    finFormAlertOk(title, toLocale("finStackMobileExt::itemNotFoundMsg").replace("{item}", edit->dis))
end


def ​

func:finFormDBBuilderDelete ​

finFormDBBuilderDelete(selectedItem, customAction: null, customMsg: null, itemTree: null, folderPath: "") ​

Axon function


meta ​

deffunc:finFormDBBuilderDelete
isfunc
liblib:finStackMobile
namefinFormDBBuilderDelete
overridable✓
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(selectedItem, customAction: null, customMsg: null, itemTree: null, folderPath: "") => do
  curRec: null
  confirmMsg: {}
  action: ""
  jsAction: ""

  if (not folderPath.isEmpty) folderPath = cleanFolderPathName(folderPath)
  if (selectedItem.isList and selectedItem.size == 1 and itemTree != "equip") selectedItem = selectedItem[0]

  //read the items to be deleted or the item
  if(selectedItem.isList and selectedItem[0].isRef)
    selectedItem = selectedItem.map(r => {id: r, dis: readById(r, false).dis})
  else if(selectedItem.isRef)
    selectedItem = {id: selectedItem, dis: readById(selectedItem, false).dis}

  if(selectedItem.isList)
    curRec = readByIds(selectedItem.map(r => r->id), false)
  else if(selectedItem.has("isFolder") or selectedItem->id.toStr.startsWith("folderPath"))
  do
    temp: readById(selectedItem->id, false)
    selectedItem = selectedItem.merge({dis: if (temp != null) temp.dis else selectedItem->id.finIdToFolderPath.split("/")[-1]})
    curRec = selectedItem
  end
  else do
    curRec = readById(selectedItem->id, false)

    if(selectedItem["dis"] == null and curRec != null)
      selectedItem = selectedItem.merge({dis: curRec.dis})
  end

  /*
    determine refresh actions
  */
  //equip tree
  if(itemTree != null and itemTree == "equip") do
    customAction = "finBuilderEquipTrash("+(if (selectedItem.isList) selectedItem.map x => x->id else selectedItem->id).toAxonCode+")"
    if(curRec.isGrid and curRec.size > 1) do
      jsAction = "window.app.RefreshBuilderTreeNodeForId('@folderPath:equip:');"
      customMsg = toLocale("finStackExt::folioFilesDeleteMsg").replace("{0}", curRec.map((r, i) => if(i == curRec.size - 1) r.set("dis", "and " + r.dis) else r.set("dis", r.dis)).colToList("dis").concat(", "))
    end
    else do
      if(curRec.isGrid)
        curRec = curRec[0]

      navMetaList: read(navMeta)->equipPath.split("/") //.map(r => reFind(r"[a-zA-Z_0-9]+", r))
      selectedNavType: curRec.finNavMetaWhoAmI
      selectedNavIndex: navMetaList.index(selectedNavType)

      if(selectedNavIndex <= 1) jsAction = "window.app.RefreshBuilderTreeNodeForId('@folderPath:equip:');"
      else if(selectedNavType == "equip" and curRec.has("equipRef")) jsAction = "window.app.RefreshBuilderTreeNodeForId('"+curRec->equipRef.toAxonCode+"');"
      else jsAction = "window.app.RefreshBuilderTreeNodeForId('"+curRec[navMetaList[selectedNavIndex-1] + "Ref"].toAxonCode+"');"
    end
  end

  //all other trees
  else if(itemTree != null)
  do
    treeTagFilters:{
      graphics: "(fin5 or graphicFolder)",
      programs: "(program or programFolder)",
      schedules: "(schedule or scheduleFolder)",
      template: "(finTemplate or templateOn or templateFolder)"
    }

    queryTag: treeTagFilters[itemTree]

    if(queryTag == null) queryTag = "("+ itemTree + " or " + itemTree + "Folder)"

    /*
      refresh tree root if no folder path
      if item has a folderPath and the folder will be empty, refresh parent instead
    */
    if(readCount(parseFilter(queryTag)) == 1)
      jsAction = "window.app.RefreshBuilderTreeNodeForId('tree'); setTimeout(function() { window.app.RefreshBuilderTreeNodeForId('@folderPath:"+itemTree+":'); }, 750);"
    else if(curRec.isGrid or folderPath.isEmpty)
      jsAction = "window.app.RefreshBuilderTreeNodeForId('@folderPath:"+itemTree+":');"
    else if(readAll(parseFilter(queryTag + " and folderPath and folderPath != \"\"")).findAll(v => cleanFolderPathName(v->folderPath).startsWith(folderPath)).size == 1)
      jsAction =  "window.app.RefreshBuilderTreeNodeForId('@folderPath:"+itemTree+":"+folderPath.split("/")[0..-2].concat("/").replace(" ", "__").replace("/", "--").replace("\"", "-QUOTE-")+"');"
    else
      jsAction = "window.app.RefreshBuilderTreeNodeForId('@folderPath:"+itemTree+":"+folderPath.replace(" ", "__").replace("/", "--").replace("\"", "-QUOTE-")+"');"

    //if deleting from a folder, refresh folder's parent then refresh it (to update badge)
    if(curRec.isGrid and not folderPath.isEmpty)
      jsAction = "window.app.RefreshBuilderTreeNodeForId('@folderPath:"+itemTree+":"+folderPath.split("/")[0..-2].concat("/").replace(" ", "__").replace("\"", "-QUOTE-").replace("/", "--")+"') ; setTimeout(function() { window.app.RefreshBuilderTreeNodeForId('@folderPath:"+itemTree+":"+folderPath.replace("/", "--").replace(" ", "__")+"') }, 1000);"

    jsAction = jsAction + " window.app.RefreshBuilderGridAt(0, 'panel');"
  end //end other trees

  /*
    construct form body and messages
  */
  if(curRec != null and ((curRec.isGrid and not curRec.isEmpty and not curRec.all(j => j == null)) or curRec.isDict))
  do
    if(curRec.isGrid) do
      curRec = curRec.findAll(v => v.has("id"))
      recList: curRec.toRecList.map(r => selectedItem.find(v => v->id == r->id)->dis).concat(", ")

      confirmMsg = {
        name: "confirmMsg",
        editorType: "label",
        text: if(customMsg != null) customMsg else toLocale("finStackMobileExt::itemWillBeDeleted").replace("{item}", recList)
      }

      action = if(customAction == null) "finHardDelete(readByIds("+curRec.colToList("id").map(r => r.toAxonCode)+"))" else customAction
    end else do
      confirmMsg = {
        name: "confirmMsg",
        editorType: "label",
        text: if(customMsg != null) customMsg else toLocale("finStackMobileExt::itemWillBeDeleted").replace("{item}", selectedItem->dis)
      }

      action = if(customAction == null) "finHardDelete(readById("+selectedItem->id.toAxonCode+"))" else customAction
    end

    body: [
      confirmMsg,
      {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
      {name: "applyButton", editorType: "button", label: toLocale("finStackExt::delete"), controlBar: true}
    ]

    return {
      "dis": toLocale("finStackExt::warning"), //title,
      "name": "finFormDBBuilderDelete",
      "body": body.toJSON,
      "cancelButton": "\$cancelButton",
      "commitButton": "\$applyButton",
      "commitAction": action,
      "completeAction": jsAction,
      "finForm": marker()
    }.toGrid.addMeta({formExecute: marker()})
  end

  // no items were found at all
  else
  do
    msg: ""

    if (selectedItem.isList and selectedItem.size() > 1) do
      msg = toLocale("finStackMobileExt::selectedItems")

      deleted: selectedItem.any(v => v->id.toStr.startsWith("p"))
      stored: selectedItem.any(v => not v->id.toStr.startsWith("p"))

      if (stored and deleted)
        msg = toLocale("finStackMobileExt::itemsDeletedOrUnable").replace("{multipleItems}", msg)
      else if (stored)
        msg = toLocale("finStackMobileExt::itemsCannotBeDeleted").replace("{multipleItems}", msg)
      else
        msg = toLocale("finStackMobileExt::itemsAlreadyDeleted").replace("{multipleItems}", msg)
    end
    else
    do
      msg = selectedItem->dis

      if (selectedItem->id.toStr.startsWith("p"))
        msg = toLocale("finStackMobileExt::itemAlreadyDeleted").replace("{item}", msg)
      else
        msg = toLocale("finStackMobileExt::itemCannotBeDeleted").replace("{item}", msg)
    end

    finFormAlertOk(toLocale("finStackMobileExt::alert"), msg)
  end
end


def ​

func:finFormDBCreateNewEquip ​

finFormDBCreateNewEquip(parentNav, parentId: null, equipNav: "", reopen: false) ​

Axon function


meta ​

deffunc:finFormDBCreateNewEquip
isfunc
liblib:finStackMobile
namefinFormDBCreateNewEquip
overridable✓
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(parentNav, parentId: null, equipNav: "", reopen: false) => do
  navMeta: read(navMeta, false)->equipPath.split("/")
  navIndex: navMeta.index(parentNav)
  parentRec: if(parentId != null) readById(parentId, false) else null

  if (equipNav == "")
    equipNav = navMeta[1]

  commitStr: "finDBCreateNewEquipCommit(\$nameInput, "+equipNav.toAxonCode+", "+parentId.toAxonCode+")"

  body: [
    {
      name: "nameInput",
      editorType: "textinput",
      prompt: toLocale("finStackMobileExt::host.label.name"),
      defVal: if(not reopen) toLocale("finStackMobileExt::newItem").replace("{item}", equipNav.capitalize) else ""
    },

    { name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true },
    { name: "applyButton", editorType: "button", label: toLocale("finStackExt::coreCreate"), controlBar: true }
  ]

  if(equipNav == "point") do
    body = body.addAll([
      {
        name: "pointKind",
        editorType: "combobox",
        prompt: toLocale("finStackMobileExt::pointKindPrompt"),
        dataProvider: [
          {dis: toLocale("finStackExt::number"), val: "Number"},
          {dis: toLocale("finStackExt::boolean"), val: "Bool"},
          {dis: toLocale("finStackExt::string"), val: "Str"},
          {dis: toLocale("finStackExt::enum"), val: "enum"}
        ].toAxonCode(),
        labelField: "dis",
        selectedValueTags: "val",
        defIndex: 0
      },

      {name: "pointType", editorType: "radio", label: "sensor", group: "navSelection", selectedValue: "sensor", defVal: true},
      {name: "pointType", editorType: "radio", label: "sp", group: "navSelection", selectedValue: "sp"},
      {name: "pointType", editorType: "radio", label: "cmd", group: "navSelection", selectedValue: "cmd"},

      {name: "spacer", editorType: "label", text: ""},

      {
        name: "fromLib",
        editorType: "checkbox",
        label: toLocale("j2FinToolsExt::createFromLib"),
      }
    ])

    commitStr = commitStr[0..-2] + ", {kind: \$pointKind, \$pointType, createFromLib: \$fromLib, cur})"
  end

  if (reopen)
    body = body.insert(0, {name: "errLabel", editorType: "label", text: toLocale("finStackMobileExt::enterNameForNewItemMsg").replace("{item}", equipNav)})

  //determine which tree node to refresh
  //points will refresh their equip tree on the next form
  parentParent: null

  if((navIndex - 1) > 0)
    parentParent = parentRec[navMeta[navIndex - 1]+"Ref"]

  js:[]

  if(equipNav == "point")
  do
    callBacks: "window.app.RefreshBuilderTreeNodeForId('"+parentId.toAxonCode+"');"

    if(readCount(point and equipRef == parentId) == 0) do
      if(parentNav == "equip" and parentRec.has("equipRef"))
        parentParent = parentRec->equipRef

      callBacks = "window.app.RefreshBuilderTreeNodeForId('"+parentParent.toAxonCode+"'); setTimeout(function() { "+callBacks+" }, 750);"
    end

    js = [
      "var equipNav = "+equipNav.toAxonCode+";",
      "if(\$fromLib == true) {",
        "window.app.InitBatchRecordEditor('" + (if (parentRec.has("point")) parentRec->equipRef.toAxonCode else parentRec->id.toAxonCode) + "','create', undefined, function() { "+callBacks+(if (parentNav != "") " try { window.app.RefreshBuilderGridAt(0, 'panel'); } catch (error) { console.log('No panel to refresh.');}" else "") + " }, finstack);",
      "}",
      "else {",
      callBacks
    ]
  end
  else
  do
    parentRecJson: (id) => do
      id.readById.findAll(val => do
        if (val.isGrid)
          return false
        return true
      end).toJSON
    end
    js = [
      //new item isnt a point and will be added to the selected branch
      "var equipNav = "+equipNav.toAxonCode+";",
      "if(equipNav !== 'point' && (("+navMeta.toAxonCode+").indexOf(equipNav) > "+navIndex+" || equipNav === 'equip'))",
      "{",
        if(parentParent != null) "window.app.RefreshBuilderTreeNodeForId('"+(if (parentParent.isRef) parentParent.toAxonCode else parentParent) +"');"
        else if ((navIndex == 0 and readCount(parseFilter(navMeta[navIndex + 1])) > 0) or navIndex > 0) "window.app.RefreshBuilderTreeNodeForId('@folderPath:equip:');"
        else "window.app.RefreshBuilderTreeNodeForId('tree'); setTimeout(function() { window.app.RefreshBuilderTreeNodeForId('@folderPath:equip:');}, 1000);",

        if(parentId != null) "setTimeout(function() { window.app.RefreshBuilderTreeNodeForId('"+parentId.toAxonCode+"');}, 1000);"
        else "",
      "}",

      //new item isnt a point and will be added to a higher branch
      "else if(equipNav !== 'point')",
      "{",
        "var newItemIndex = ("+navMeta.toAxonCode+").indexOf(equipNav);",

        //higher branch is not the top most navMeta (usually site)
        "if(newItemIndex > 1 && "+(parentId != null)+") {",
          "var refToRefresh = ("+navMeta.toAxonCode+")[newItemIndex - 1];",
          "window.app.RefreshBuilderTreeNodeForId('@'+"+(if(parentId != null) parentRecJson(parentId) else "") + "[refToRefresh + 'Ref']);",
        "}",

        //higher branch is the top most navMeta (usually site)
        "else window.app.RefreshBuilderTreeNodeForId('@folderPath:equip:');",
      "}",
    ]
  end

  js = js.addAll([
    if (parentNav != "") "try { window.app.RefreshBuilderGridAt(0, 'panel'); } catch(error) { console.log('No panel to refresh.'); }" else "",
    "var promise;",
    "if(equipNav == 'site' || equipNav == 'floor') promise = finstack.eval('read(justAdded and '+equipNav+' and dis == \$nameInput).diff({-justAdded}).commit');",
    "else promise = finstack.eval('read(justAdded and '+equipNav+' and navName == \$nameInput).diff({-justAdded}).commit');",
  ])

  if (not (["point", "equip", "site"]).contains(equipNav))
    js = js.addAll([
      "promise.then(function(event) {",
        "var result = event.result.toObj(false, false, true);",
        "window.app.InitPropertyEditor(result.id, function () { window.app.RefreshBuilderTreeNodeForId('"+parentId.toAxonCode+"'); "+(if (parentNav != "") "try { window.app.RefreshBuilderGridAt(0, 'panel'); } catch(error) { console.log('No panel to refresh.'); }" else "")+" })",
      "})"
    ])

  if (equipNav == "point") js = js.add("}")

  { "dis": toLocale("finStackMobileExt::createNewGenericItem").replace("{item}", equipNav.capitalize),
    "name": "finFormCreateNewEquip" + (if(reopen) random(1..1000) else ""),
    "body": body.toJSON,
    "cancelButton": "\$cancelButton",
    "commitButton": "\$applyButton",
    "commitAction": "if(isEmpty(\$nameInput)) finFormDBCreateNewEquip("+parentNav.toAxonCode+", "+parentId.toAxonCode+", "+equipNav.toAxonCode+") else " + commitStr,
    "completeAction": js.concat(""),
    "finForm": marker()
  }.toGrid.addMeta({formExecute: marker()})
end


def ​

func:finFormDBSelectEditDelete ​

finFormDBSelectEditDelete(details, folderPath: "", targetRef: null) ​

Axon function


meta ​

deffunc:finFormDBSelectEditDelete
isfunc
liblib:finStackMobile
namefinFormDBSelectEditDelete
overridable✓
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(details, folderPath: "", targetRef: null) => do
  langItems: {
    edit: {
      localStr: toLocale("finStackExt::coreEdit"),
      prompt:  toLocale("finStackMobileExt::selectItemsToEditPrompt").replace("{item}", details->treeType),
    },

    delete: {
      localStr: toLocale("finStackExt::coreEdit"),
      prompt:  toLocale("finStackMobileExt::selectItemsToDeletePrompt").replace("{item}", details->treeType)
    },
  }

  dataP: ""
  action: ""
  jsAction: ""
  formTitle: langItems[details->actionType]["localStr"]
  returnIdOnly: false
  objStr: ""

  //schedules
  if(details->treeType == "schedule")
  do
    if(details->actionType == "edit") return finFormEditSchedule(null, "")
    else if(details->actionType == "delete") return scheduleConfirmDeleteForm(null, null, false, "")
  end

  //jobs
  if(details->treeType == "job")
  do
    if(details->actionType == "edit") return jobCreateForm("select", null, null, true)
    else if(details->actionType == "delete") return jobTrashForm()
  end

  //graphic
  else if(details->treeType == "graphic") do
    dataP = "readAll(fin5).sort(\"dis\")"
    returnIdOnly = true

    if(details->actionType == "edit") do
      completeAct: null

      if(targetRef != null)
        completeAct = {completeAction: "window.open((finstack.pathPrefix || '')+'/finMobile/" + context()->projName + "#frame?targetRef="+targetRef.toAxonCode+"&url=' + encodeURIComponent('/graphicsBuilder/" + context()->projName + "/#graphicRef={item}&targetRef="+targetRef.toAxonCode+"'))"}
      else
        completeAct = {completeAction: "window.open((finstack.pathPrefix || '')+'/finMobile/" + context()->projName + "#frame?url=' + encodeURIComponent('/graphicsBuilder/" + context()->projName + "/#graphicRef={item}'))"}

      action = "finStackMenuOkForm("+toLocale("finStackExt::warning").toAxonCode+", "+toLocale("finStackMobileExt::openGraphicBuilderInNewWindow").toAxonCode+", "+completeAct.toAxonCode+".merge({itemId: \$selectItem, includeCancel: true}))"
    end else
      action = "finFormDBBuilderDelete(\$selectItem, null, null, \"graphics\", "+folderPath.toAxonCode+")"
      //action = "finStackMenuDeleteConfirm(\$selectItem, \"Graphic\", false, true)"
  //programs
  end else if(details->treeType == "program") do
    dataP = "readAll(programOn and not emptyFolder).sort(\"name\")"
    returnIdOnly = true

    if(details->actionType == "edit") do
      extra: ""
      completeAct: null

      if(targetRef != null) extra = "&equipRef="+targetRef.toAxonCode

      completeAct = {completeAction: "var win = window.open((finstack.pathPrefix || '')+'/finMobile/"+context()->projName+"#frame?"+(if(targetRef != null) "targetRef="+targetRef.toAxonCode+"&" else "")+ "url='+encodeURIComponent('/pod/finBlockProgrammingExt/index.html#targetRef={item}&proj="+context()->projName+"&title=showSettings"+extra+"')); \n" +
        "setTimeout(function(){\n"+
        "  win.app.ObtainMenu(\n"+
        "    '"+finGetCurrentUser()->username+"',\n"+
        "    '"+targetRef.toAxonCode+"',\n"+
        "    'taskData',\n"+
        "    {\n"+
        "      iconFunc:\"blineVariableIcon("+targetRef.toAxonCode+")\",\n"+
        "      badgeTooltipFunc:\"blineTaskVarBadgeTooltip("+targetRef.toAxonCode+")\",\n"+
        "      iconClassFunc:\"blineTaskVarIconColor()\",\n"+
        "      badgeValueFunc:\"blineTaskVarBadgeVal()\",\n"+
        "      display:\"name\",\n"+
        "      hasBadge:true,\n"+
        "      iconTooltipFunc:\"blineTaskVarTip("+targetRef.toAxonCode+")\",\n"+
        "      hideBackButton:true,\n"+
        "      keepOpen:true,\n"+
        "      iconType:\"class\",\n"+
        "      funcCall:\"blineTaskMenu("+targetRef.toAxonCode+", readById({item}).dis, true)\",\n"+
        "      badgeTypeFunc:\"blineTaskVarBadgeColor("+targetRef.toAxonCode+")\"\n"+
        "    }\n"+
        "  )\n"+
        "}, 2000)"}

      //completeAct = {completeAction: "window.app.LoadApplication('/pod/finBlockProgrammingExt/index.html#targetRef={item}&proj="+context()->projName+"&title=showSettings"+extra+"', '', '"+targetRef.toAxonCode+"')"}
      action = "finStackMenuOkForm("+toLocale("finStackExt::warning").toAxonCode+", "+toLocale("finStackMobileExt::openBlineInNewWindow").toAxonCode+", "+completeAct.toAxonCode+".merge({itemId: \$selectItem, includeCancel: true}))"
    end else
      action = "finFormDBBuilderDelete(\$selectItem, null, null, \"programs\", "+folderPath.toAxonCode+")"
      //action = "finStackMenuDeleteConfirm(\$selectItem, \"bLine Program\", false, true)"
  //bacnet
  end else if(details->treeType == "BACnet Connector")
  do
    dataP = "readAll(bacnetConn).map(r => r.merge({dis: r.dis})).sort(\"dis\")"
    returnIdOnly = true

    if(details->actionType == "edit")
      action = "finFormManualAddEditBacnet(\$selectItem, null, \"ip\", "+folderPath.toAxonCode+")"
    else if(details->actionType == "delete")
      action = "finFormConfirmChangesAlert(\"(\$selectItem).each x => x.readById.finHardDelete\", " +
        "toLocale(\"finStackExt::folioFilesDeleteMsg\").replace(\"{0}\", (\$selectItem).toRecList.map(r => r.dis).concat(\", \")), " +
        "\"window.app.RefreshBuilderTreeNodeForId('@folderPath:bacnetConn:'); window.app.RefreshBuilderGridAt(0, 'panel')\")"
  //haystack
  end else if(details->treeType == "Haystack Connector")
  do
    dataP = "readAll(haystackConn).map(r => r.merge({dis: r.dis})).sort(\"dis\")"
    returnIdOnly = true

    if(details->actionType == "edit")
      action = "finFormAddEditHaystackConnector(\$selectItem, null, "+folderPath.toAxonCode+")"
    else if(details->actionType == "delete")
      action = "finFormConfirmChangesAlert(\"(\$selectItem).each x => x.readById.finHardDelete\", " +
        "toLocale(\"finStackExt::folioFilesDeleteMsg\").replace(\"{0}\", (\$selectItem).toRecList.map(r => r.dis).concat(\", \")), " +
        "\"window.app.RefreshBuilderTreeNodeForId('@folderPath:haystackConn:'); window.app.RefreshBuilderGridAt(0, 'panel')\")"
  end

  // generic trees
  else
  do
    dataP = if(details["itemQuery"] != null) details->itemQuery else "readAll("+details->treeType+").map(r => r.merge({dis: r.dis})).sort(\"dis\")" //" or "+details->treeType+"Folder

    if (details->actionType == "edit")
    do
      if (details["antPod"] == null)
        action = "finFormDBAddEdit("+details->treeType.toAxonCode+", \$selectItem, null, "+folderPath.toAxonCode+", false, null, "+details->treeType.endsWith("Conn")+")"
      else
      do
        returnIdOnly = true
        jsAction = "top.app.ShowRemotePopup(null, '/pod/"+details->antPod->dis+"/index.html#"+details->antPod->form+"/ \$selectItem', {size: {w:'100%', h:'100%'}, position: {x:'center', y:'middle'}}); " + setRemotePopupBackground()
      end
    end
    else if(details->actionType == "delete")
      action = "finFormDBBuilderDelete(\$selectItem, null, null, "+details->treeType.toAxonCode+", "+folderPath.toAxonCode+")"
  end

  /*
    if folderPath is not empty,
    add filter for data to only show items under that folderPath
  */
  if(not folderPath.isEmpty())
    dataP = dataP + ".findAll(v => v.has(\"folderPath\") and not v->folderPath.isEmpty and cleanFolderPathName(v->folderPath).startsWith("+cleanFolderPathName(folderPath).toAxonCode+"))"

  //create form body
  body: [
    {
      name: "selectItem",
      editorType: if(details->actionType != "delete") "combobox" else "list",
      listType: if(details->treeType == "graphic" and details->actionType == "edit") "radio" else if(details->actionType == "delete") "checkbox" else null,
      prompt: langItems[details->actionType]["prompt"],
      dataProvider: dataP,
      label: "dis",
      selectedValueTags: if(returnIdOnly) "id" else "id, dis",
      defIndex: 0,
      height: 150
    },

    {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
    {name: "applyButton", editorType: "button", label: langItems[details->actionType]["localStr"], controlBar: true}
  ]

  objStr = if (details["objStr"] != null) details->objStr else details->treeType.split(" ").map(r => r.capitalize).concat(" ")
  formTitle = formTitle + " " + objStr

  if (eval(dataP).size == 0)
    return finFormAlertOk(formTitle, toLocale("finStackMobileExt::noItemCouldBeFound").replace("{objType}", objStr.decapitalize))

  {
    "dis": formTitle,
    "name": "finFormDBSelectEditDelete",
    "body": body.toJSON,
    "cancelButton": "\$cancelButton",
    "commitButton": "\$applyButton",
    "commitAction": action,
    "completeAction": jsAction,
    "finForm": marker()
  }.toGrid.addMeta({formExecute: marker()})
end


def ​

func:finFormEditSchedule ​

finFormEditSchedule(id: null, folderPath: null) ​

Form to edit schedules.


meta ​

deffunc:finFormEditSchedule
distoLocale("finStackMobileExt::scheduleMenuEditTip")
isfunc
liblib:finStackMobile
namefinFormEditSchedule
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(id: null, folderPath: null) => do
  if(id == null or id.isStr) do
    body: [
      {
        name:"sched",
        editorType:"combobox",
        prompt: toLocale("finStackMobileExt::selectScheduleToEdit"),
        labelField: "dis",
        selectedValueTags: "id",
        defIndex: 0,
        dataProvider: if(id == null) "readAll(schedule).sort(\"dis\")" else "readAll(schedule and folderPath).findAll(v => v.has(\"folderPath\") and (v->folderPath.startsWith("+(id + "/").toAxonCode+") or (\"/\" + v->folderPath).startsWith("+(id + "/").toAxonCode+") or \"/\" + v->folderPath == "+id.toAxonCode+" or v->folderPath == "+id.toAxonCode+")).sort(\"dis\")"
      },

      { name:"cancelButton", editorType:"button", label:toLocale("finStackExt::cancel"), controlBar:true },
      { name:"applyButton", editorType:"button", label:toLocale("finStackExt::next"), controlBar:true }
    ]

    {
      "dis": toLocale("finStackMobileExt::scheduleMenuEditTip"),
      "name": "finFormEditScheduleSelect",
      "body": body.toJSON,
      "cancelButton": "\$cancelButton",
      "commitButton": "\$applyButton",
      "commitAction": "finFormEditSchedule(\$sched, "+folderPath.toAxonCode+")",
      "finForm": marker(),
    }.toGrid.addMeta({formExecute: marker()})
  end
  else do
    if(id.isRef) do
      sched: readById(id)

      types: [{o:"Boolean",a:"Bool"},{o:"Number",a:"Number"},{o:"String",a:"Str"}] //type
      if(sched["kind"] == "Str" and sched.has("enum")) sched = sched.set("kind","Enum")
      else sched = sched.set("kind", types.find(x=> x->a == sched->kind)->o)

      def: null //default value
      try def = sched->scheduleGrid.find(x=> x.has("defaultEvent")) catch 0
      if(def == null) sched = sched.set("hasDef", false)
      else sched = sched.set("hasDef", true)

      //  update
      currentUser: finGetCurrentUser()
      currentUsrZone: currentUser["tz"]
      if (currentUsrZone == null and currentUser["userProtoRef"] != null)
        currentUsrZone = currentUser->userProtoRef.userReadById->tz
      else
        currentUsrZone = now().tz
      currentTimeZoneName: if (sched.has("tz")) sched->tz else now().tz
      allTimezones: tzdb().toRecList
      defaultZone: now().tz

      //  find the full-name of the user zone
      userZone: allTimezones.find r => r->fullName == currentUsrZone or r->name == currentUsrZone
      selectedZone: allTimezones.find r => r->fullName == currentTimeZoneName or r->name == currentTimeZoneName
      defaultZoneFullName: allTimezones.find r => r->fullName == defaultZone or r->name == defaultZone

      //  add the default ones
      allTimezones = allTimezones.insert(0, {fullName: "System (Default - " +defaultZoneFullName->fullName+ ")", isDefault: true})

      //  check and add user-zone
      if (userZone != null)
        allTimezones = allTimezones.insert(1, {fullName: "User (" +userZone->fullName+ ")", userZone: userZone->fullName})
      //---

      selectedZoneIndex: 0
      if (sched.has("tz")) do
        if (userZone != null and userZone->fullName == selectedZone->fullName)
          selectedZoneIndex = 1
        else
          selectedZoneIndex = allTimezones.map(r => r->fullName).index(selectedZone->fullName)
      end

      body: [
        {name: "name", editorType: "textinput", prompt: toLocale("finStackMobileExt::pointsScheduleName"), defVal: sched->dis},
        {name: "label", editorType: "label", prompt: toLocale("finStackMobileExt::scheduleType"), text: sched->kind},
        {name: "default", editorType: "checkbox", label: toLocale("finStackMobileExt::defValue"), defVal: sched->hasDef},
        {name: "tags", editorType: "textinput", prompt: toLocale("finStackMobileExt::tagEditor"), defVal: ""},
        {name: "tz", editorType: "combobox", prompt: toLocale("finStackMobileExt::finTimezone"), labelField: "fullName", selectedValueTags: "fullName,isDefault,userZone", defIndex: selectedZoneIndex, dataProvider: allTimezones.toAxonCode},
        {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
        {name: "applyButton", editorType: "button", label: toLocale("finStackExt::coreApply"), controlBar: true}
      ]

      if(sched->kind == "Boolean") do
        tmp: sched["enum"]
        if (tmp.isStr) do
          if (not tmp.contains(",")) tmp = tmp + "," + toLocale("finStackExt::valTrue")
          tmp = tmp.split(",")
        else tmp = [toLocale("finStackExt::valFalse"), toLocale("finStackExt::valTrue")]

        tmp = [{o:tmp[1],a:true},{o:tmp[0],a:false},{o:toLocale("finStackExt::valNull"),a:"null"}].toAxonCode

        if(def == null or def["val"] == null) def = 2
        else if(def->val == true ) def = 0
        else if(def->val == false) def = 1

        body = body.add({name: "opt", editorType: "combobox", prompt: toLocale("finStackExt::gbValue"), dataProvider: tmp, labelField: "o", selectedValueTags: "a", defIndex: def})
      end
      else if(sched->kind == "Number") do
        if(def == null or def["val"] == null) def = {val: 0}

        body = body.add({name: "opt", editorType: "numericstepper", prompt: toLocale("finStackExt::gbValue"), defVal: def->val})
      end
      else if(sched->kind == "String") do
        if(def == null or def["val"] == null) def = {val: ""}

        body = body.add({name: "opt", editorType: "textinput", prompt: toLocale("finStackExt::gbValue"), defVal: def->val})
      end
      else if(sched->kind == "Enum") do
        tmp: sched->enum.split(",").findAll(x=> x!="")

        if(def == null or def["val"] == null) ind: 0
        else ind: tmp.index(def->val)

        body = body.add({name: "opt", editorType: "combobox", prompt: toLocale("finStackExt::gbValue"), dataProvider: tmp.toAxonCode,
          labelField: "val", selectedValueTags: "val", defIndex: ind})
      end

      /*
        if folderPath is present,
        assume schedule is deleted from db builder
        and create refresh calls
      */
      jsAction: ""

      if(folderPath != null) do
        folderId: "@folderPath:schedules:"

        if(not folderPath.isEmpty()) do
          parentId: folderId + cleanFolderPathName(folderPath).split("/")[0..-2].concat("--").replace(" ", "__")
          folderId = folderId + cleanFolderPathName(folderPath).replace("/", "--").replace(" ", "__")

          jsAction = "window.app.RefreshBuilderTreeNodeForId('"+parentId+"'); setTimeout(function() {window.app.RefreshBuilderTreeNodeForId('"+folderId+"');}, 500); window.app.RefreshBuilderGridAt(0, 'panel');"
        end

        else
          jsAction = "window.app.RefreshBuilderTreeNodeForId('"+folderId+"'); window.app.RefreshBuilderGridAt(0, 'panel');"
      end

      {
        "dis": toLocale("finStackMobileExt::scheduleMenuEditTip"),
        "name": "finFormEditSchedule",
        "body": body.toJSON,
        "cancelButton": "\$cancelButton",
        "commitButton": "\$applyButton",
        "commitAction": "finFormEditSchedule(["+id.toAxonCode+", \$name, \$default, \$opt, \$tags, \$tz])",
        "completeAction": jsAction + "window.app.RefreshCurrentAppData();",
        "finForm": marker(),
      }.toGrid.addMeta({formExecute: marker()})
    end
    /////////////////////
    else if(id.isList) do
      sched: readById(id[0])

      try dat: sched->scheduleGrid
      catch dat: [].toGrid

      dat = dat.findAll(x=> not x.has("defaultEvent"))

      if(id[2]) dat = dat.addRow({end: 00:00:00, defaultEvent: marker(), val: if (id[3] == "null") null else id[3], weekdays: "sun,mon,tue,wed,thu,fri,sat", start: 00:00:00})

      zoneVal: id[5]
      if (zoneVal["isDefault"] == null) do
        if (zoneVal["userZone"] != null)
          zoneVal = zoneVal->userZone
        else
          zoneVal = zoneVal->fullName
      end else
        zoneVal = removeMarker()

      sched.diff({dis: id[1], scheduleGrid: dat, tz: zoneVal}).commit
      if(id[4].trim != "") sched->id.readById.diff(eval("{"+id[4]+"}")).commit
    end
  end
end


def ​

func:finFormManualAddEditBacnet ​

finFormManualAddEditBacnet(curConn: null, refill: null, connType: "ip", folderPath: null) ​

Axon function


meta ​

deffunc:finFormManualAddEditBacnet
isfunc
liblib:finStackMobile
namefinFormManualAddEditBacnet
overridable✓
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(curConn: null, refill: null, connType: "ip", folderPath: null) => do
  title: toLocale("finStackMobileExt::addBacnetConnector")
  commitButton: toLocale("finStackExt::add")

  disDef: ""
  hostDef: ""
  devInstDef: null
  netDef: null
  macDef: null
  comPortDef: ""
  mstpDef: null
  baudDef: 6

  baudRates:[{val: 9600},{val: 14400},{val: 19200},{val: 28800},{val: 38400},{val: 57600}, {val:76800}, {val: 115200}] //{val: 300},{val: 600},{val: 1200},{val: 2400},{val: 4800},
  action: ""

  if(curConn != null) do
    title = toLocale("finStackMobileExt::editBacnetConnector")
    commitButton = toLocale("finStackExt::coreApply")
  end

  if(refill != null) do
    disDef = refill->disName
    if(connType == "ip") hostDef = refill->ip
    else comPortDef = refill->comPort

    if(not refill->deviceInstance.isEmpty) devInstDef = refill->deviceInstance[0]
    if(not refill->netNum.isEmpty) netDef = refill->netNum[0]

    if(connType == "ip" and not refill->macAdd.isEmpty) macDef = refill->macAdd[0]
    else if(connType == "mstp") do
      if(not refill->mstpAdd.isEmpty) mstpDef = refill->mstpAdd
      if(not refill->baudRate.isEmpty) baudDef = baudRates.toGrid.colToList("val").index(refill->baudRate[0])
    end
  end else if(curConn != null) do
    connRec: readById(curConn)
    disDef = connRec->dis
    uriVal: connRec->uri.toStr

    if(connRec.has("folderPath"))
      folderPath = connRec->folderPath

    if(uriVal.startsWith("bacnet://")) do
      uriVal = uriVal.replace("bacnet://", "")
      hostDef = try uriVal.split("/")[0] catch ""
      macDef = try reFind(r"dadr=[abcdef\d]+", uriVal.split("/")[1].split("?")[1]).replace("dadr=", "").parseInt(16) catch null
    end else do
      connType = "mstp"
      uriVal = uriVal.replace("bacnetmstp://", "")
      comPortDef = try uriVal.split("/")[0].split(":")[0] catch ""
      mstpDef = try uriVal.split("/")[0].split(":")[1] catch ""
      baudDef = try baudRates.toGrid.colToList("val").index(reFind(r"baud=\d+", uriVal.split("/")[1].split("?")[1]).replace("baud=", "").parseNumber) catch 7
    end

    devInstDef = try uriVal.split("/")[1].split("?")[0].parseNumber catch null
    netDef = try reFind(r"dnet=\d+", uriVal.split("/")[1].split("?")[1]).replace("dnet=", "").parseNumber catch null
  end

  body: [
    {
      name: "displayName",
      editorType: "textinput",
      prompt: toLocale("finStackMobileExt::hostDisplayName")+":",
      defVal: disDef
    },

    {
      name: "deviceInst",
      editorType: "numericstepper",
      prompt: toLocale("finStackMobileExt::deviceInstance")+":",
      minVal: 0,
      defVal: devInstDef
    },

    {
      name: "networkNum",
      editorType: "numericstepper",
      prompt: toLocale("finStackMobileExt::networkNumber")+":",
      minVal: 0,
      defVal: netDef
    },

    {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
    {name: "applyButton", editorType: "button", label: commitButton, controlBar: true}
  ]

  if(connType == "ip") do
    body = body.insert(1, {
      name: "hostAddr",
      editorType: "textinput",
      prompt: toLocale("finStackMobileExt::rightMenuHost")+":",
      defVal: hostDef
    }).insert(4, {
      name: "macAddr",
      editorType: "numericstepper",
      prompt: toLocale("finStackMobileExt::macAddress")+":",
      minVal: 0,
      defVal: macDef
    })

    action = "finManualAddEditBacnetCommit({ip: \$hostAddr, disName: \$displayName, deviceInstance: [\$deviceInst], netNum: [\$networkNum], macAdd: [\$macAddr]}, \"ip\", "+curConn.toAxonCode+", "+folderPath.toAxonCode+")"
  end else if(connType == "mstp") do
    body = body.insertAll(1, [
      {
        name:"comPort",
        editorType: "textinput",
        prompt: toLocale("finStackMobileExt::comPort"),
        defVal: comPortDef
      },

      {
        name: "mstpAddr",
        editorType: "numericstepper",
        prompt: toLocale("finStackMobileExt::mstpAddress"),
        minVal: 0,
        defVal: mstpDef
      }
    ]).add({
      name: "baudNum",
      editorType: "combobox",
      prompt: toLocale("finStackMobileExt::baudRate"),
      dataProvider: baudRates.toAxonCode,
      labelField: "val",
      selectedValueTags: "val",
      defIndex: baudDef
    })

    action = "finManualAddEditBacnetCommit({comPort: \$comPort, disName: \$displayName, deviceInstance: [\$deviceInst], netNum: [\$networkNum], mstpAdd: [\$mstpAddr], baudRate:[\$baudNum]}, \"mstp\", "+curConn.toAxonCode+", "+folderPath.toAxonCode+")"
  end

  if(refill != null) body = body.insert(0, {name: "err", editorType: "label", text: "Make sure all inputs are filled out."})

  jsAction:"window.app.RefreshBuilderTreeNodeForId('@folderPath:bacnetConn:'); window.app.RefreshBuilderGridAt(0, 'panel')"
  isEmptyFolder: false

  if(folderPath != null)
  do
    fullPath: folderPath

    if(folderPath.startsWith("@"))
    do
      objRec: readById(folderPath.replace("@", "").parseRef, false)

      if(objRec != null and objRec.has("folderPath"))
        fullPath = cleanFolderPathName(objRec->folderPath)

      if(fullPath == null) fullPath = ""

      if(objRec.has("emptyFolder"))
      do
        isEmptyFolder = true
        fullPath = cleanFolderPathName(fullPath + "/" + objRec.dis)
      end
    end

    jsAction = "window.app.RefreshBuilderTreeNodeForId('@folderPath:bacnetConn:"+fullPath.replace("/", "--").replace(" ", "__").replace("\"", "-QUOTE-")+"');"

    if(isEmptyFolder)
    do
      if(fullPath.split("/").size > 1)
        fullPath = fullPath.split("/")[0..-2].concat("/")
      else
        fullPath = ""

        jsAction = "window.app.RefreshBuilderTreeNodeForId('@folderPath:bacnetConn:"+fullPath.replace("/", "--").replace(" ", "__").replace("\"", "-QUOTE-")+"'); " +
                   "setTimeout(function() { "+jsAction+" }, 1000);"
    end

    jsAction = jsAction + " window.app.RefreshBuilderGridAt(0, 'panel')"
  end

  { "dis": title,
    "name": "finFormManualAddBacnet" + (if(refill != null) random(1..1000) else ""),
    "body": body.toJSON,
    "cancelButton": "\$cancelButton",
    "commitButton": "\$applyButton",
    "commitAction": action,
    "completeAction": jsAction,
    "finForm": marker()
  }.toGrid.addMeta({formExecute: marker()})
end


def ​

func:finFormManualOverrideAuto ​

finFormManualOverrideAuto(targetRef, autoAll: true, level: 8) ​

Axon function


meta ​

deffunc:finFormManualOverrideAuto
isfunc
liblib:finStackMobile
namefinFormManualOverrideAuto
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(targetRef, autoAll: true, level: 8) => do
  currentUser: finGetCurrentUser()

  curLoc: if(targetRef != null) readById(targetRef, false) else {dis:toLocale("finStackMobileExt::theTopLevel")}
  title: if(autoAll) toLocale("finStackMobileExt::autoAll") else toLocale("finStackMobileExt::autoSelected")

  body: [
    {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
    {name: "applyButton", editorType: "button", label: toLocale("finStackExt::coreApply"), controlBar: true}
  ]

  // target found
  if(curLoc != null) do
    pointDataStr: "point and (write"+level+" or writeLevel == "+level+")"
    action: "({query}).each(x => invoke(x->id, x->targetActionName, {self: x->id}))"
    if(curLoc.has("id")) pointDataStr= finNavMetaWhoAmI(curLoc)+"Ref == "+targetRef.toAxonCode+" and "+pointDataStr

    matchingPts: readAll(parseFilter(pointDataStr))
    autoablePts: []

    // no points found
    if(matchingPts.isEmpty())
      return finFormAlertOk(title, toLocale("finStackMobileExt::noPointsOverriden").replace("{{number}}", level.toStr).replace("{{equipName}}", curLoc.dis))

    matchingPts.each(pt =>
    do
      actionName: null

      //manual
      if (level == 8) actionName = finGetPtActionName(currentUser["actionAccessFilter"], pt->id, "pointAuto")

      //emergency
      else actionName = finGetPtActionName(currentUser["actionAccessFilter"], pt->id, "pointEmergencyAuto")

      if (actionName != null)
        autoablePts = autoablePts.add({targetActionName: actionName, dis: pt.dis, id: pt->id})
    end)

    // user has no hvac_finCat access to any points
    if(autoablePts.size == 0)
      return finFormAlertOk(toLocale("finStackExt::regError"), toLocale("finStackMobileExt::requiredActionFilterMissingOnUser").replace("{user}", currentUser.dis))

    // pick which ones to auto
    if(not autoAll) do
      body = body.add({
        name: "points",
        editorType: "list",
        listType: "checkbox",
        prompt: toLocale("finStackMobileExt::selectPointsToAuto"),
        dataProvider: "("+autoablePts.toAxonCode+").toGrid.sort(\"dis\")", //pointDataStr+".map(r => r.merge({dis: r.dis})).sort(\"dis\")", //.findAll(v => v->actions.ioReadZinc.find(z => z.dis.lower.contains(\"manual\") and z.dis.lower.contains(\"auto\")) == null || )
        labelField: "dis",
        selectedValueTags: "id, targetActionName",
        height: 150
      })

      action = action.replace("{query}", "(\$points)")
    end

    //auto all points
    else do
      body = body.add({
        name: "allLabel",
        editorType: "label",
        text: (if(level == 1) toLocale("finStackMobileExt::emergencyAllPoints") else toLocale("finStackMobileExt::manualAllPoints")).replace("{{equipName}}", curLoc.dis)
      })

      action = action.replace("{query}", autoablePts.toAxonCode) // + ".colToList(\"id\")")
    end

    menuSettings: {
      funcCall: "manualOverrideMenu("+targetRef.toAxonCode+")",
      hideBackButton: true,
      display: "dis",
      keepOpen: true
    }

    { "dis": title,
      "name": "finFormManualOverrideAuto",
      "body": body.toJSON,
      "cancelButton": "\$cancelButton",
      "commitButton": "\$applyButton",
      "commitAction": action,
      "completeAction": "window.app.ObtainMenu(null, '"+targetRef.toAxonCode+"', 'overridesApp', " + menuSettings.toAxonCode + ")",
      "finForm": marker()
      }.toGrid.addMeta({formExecute: marker()})
  end // end if target found
end


def ​

func:finFormNewHaystackPassword ​

finFormNewHaystackPassword(haystackConnRef, changesDict) ​

Axon function


meta ​

deffunc:finFormNewHaystackPassword
isfunc
liblib:finStackMobile
namefinFormNewHaystackPassword
overridable✓
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(haystackConnRef, changesDict) => do

  body: [
    {
      name: "pass",
      editorType: "textinput",
      prompt: toLocale("finStackMobileExt::newPassword") + ":",
      password: true
    },

    {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
    {name: "applyButton", editorType: "button", label: toLocale("finStackExt::coreApply"), controlBar: true}
  ]

  return {
    "dis": toLocale("finStackMobileExt::changeHaystackConnPass"),
    "name": "finFormNewHaystackPassword" + random(1..1000),
    "body": body.toJSON,
    "cancelButton": "\$cancelButton",
    "commitButton": "\$applyButton",
    "commitAction": "finAddEditHaystackConnectorCommit("+haystackConnRef.toAxonCode+", "+changesDict.toAxonCode+".merge({password:\$pass}))",
    "finForm": marker()
  }.toGrid.addMeta({formExecute: marker()})
end


def ​

func:finFormRunToolsOnMulti ​

finFormRunToolsOnMulti(id, reopened: false) ​

Axon function


meta ​

deffunc:finFormRunToolsOnMulti
isfunc
liblib:finStackMobile
namefinFormRunToolsOnMulti
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(id, reopened:false) => do
  treePath: "finEquipRefTree(@"+id+", treePath)"

  if(id == null) treePath="treeName:equip"

  body: [
    {
      name: "childTree",
      editorType: "ractive",
      ractiveType: "tree",
      prompt: toLocale("finStackMobileExt::dbSelectTargets"),
      path: treePath,
      labelField: "treeDisplay",
      selectedValueTags: "id",
      tapSelectEnabled: true,
      allowMultiSelect: true,
      height: 450
    },

    {
      name: "advanced",
      editorType: "checkbox",
      label: toLocale("finStackMobileExt::dbShowAdvanced")
    },

    { name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true },
    { name: "commitButton", editorType: "button", label: toLocale("finStackExt::next"), controlBar: true}
  ]

  if(reopened) body = body.insert(0, {name: "missingMsg", editorType: "label", text: toLocale("finStackMobileExt::dbPleaseSelect")})

  { "dis":toLocale("finStackMobileExt::dbOpenToolsName"),
    "name": if(not reopened) "finSelectToolTargets" else "finSelectToolTargets" + random(1..10000),
    "body":body.toJSON,
    "width": 450,
    "cancelButton": "\$cancelButton",
    "commitButton":"\$commitButton",
    "commitAction": "if((\$childTree.isEmpty) and \$advanced != true) finFormRunToolsOnMulti("+id.toAxonCode+", true) else finFormSelectTool("+id.toAxonCode+", \$childTree, \$advanced)",
    "finForm": marker()
  }.toGrid.addMeta({formExecute: marker()})
end


def ​

func:finFormSchedulePointPriority ​

finFormSchedulePointPriority(ids, prio: null) ​

Axon function


meta ​

deffunc:finFormSchedulePointPriority
isfunc
liblib:finStackMobile
namefinFormSchedulePointPriority
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(ids, prio: null) => do
  if(prio == null)
  do
    pris: (2..16).map(x=> x).findAll(x=> x != 8)
    ids = ids.map(x=> if(x.isRef) "@"+x else x)
    id: ids[0][1..-1].parseRef.readById
    sched: 15

    if(id.has("schedulable"))
      sched = id->schedulable

    js: [
      "function checkJobStatus(jobHandle) {",
        "var promise;",
        "if (jobHandle === undefined) {",
          "promise = finstack.evalAll(['jobStatusAll().find(v => v->dis.contains(\"pointWrite\") and v->started > "+now().toAxonCode+")']);",
        "} else {",
          "promise = finstack.evalAll(['jobStatusAll(\"'+jobHandle+'\")[0]']);",
        "}",
        "promise.then(function(event) {",
          "var jobStat = event.result[0].toObj(false, false, true);",
          "var isDone = jobStat['jobStatus'].startsWith('done');",
          "if (isDone) {",
            "window.top.app.HideLoader();",
            "window.app.RefreshBuilderGridAt(0, 'panel');",
          "} else {",
            "window.top.app.HideLoader();",
            "window.top.app.ShowLoader(languageManager['loaderUpdating']);",
            "setTimeout(function(){ checkJobStatus(jobStat['handle']); }, 1000);",
          "}",
        "});",
      "}",
      "window.top.app.ShowLoader(languageManager['loaderUpdating']);",
      "checkJobStatus();"
    ]

    body: [
      {
        name: "prio",
        editorType: "combobox",
        prompt: toLocale("finStackMobileExt::selectPointPriority"),
        labelField: "val",
        selectedValueTags: "val",
        defIndex: pris.index(sched),
        dataProvider: pris.toAxonCode
      },

      { name:"cancelButton", editorType:"button", label:toLocale("finStackExt::cancel"), controlBar:true},
      { name:"commitButton", editorType:"button", label:toLocale("finStackExt::coreApply"), controlBar:true }
    ]

    {
      "dis": toLocale("finStackMobileExt::schedulePointPriority"),
      "name": "finFormSchedulePointPriority",
      "body": body.toJSON,
      "cancelButton": "\$cancelButton",
      "commitButton": "\$commitButton",
      "commitAction": "finFormSchedulePointPriority("+toStr(ids)+", \$prio)",
      "completeAction": js.concat("\n"),
      "finForm": marker()
    }.toGrid.addMeta({formExecute: marker()})
  end
  else do
    ids.toRecList.each rec=> do
      if(rec.has("schedulable") and rec->schedulable.isNumber) do
        y: rec->schedulable
        x: pointWriteArray(rec)[y - 1]
        if(x.has("val")) rec.pointWrite(x->val, prio, x->who)
        eval("jobRun([jobSleep(1sec), pointWrite(@"+rec->id+", null, "+y+", \"null\")])")
        //rec.pointWrite(null, y, "candy")
      end
      rec.diff({schedulable: prio}).commit
    end
  end
end


def ​

func:finFormSelectBacnetType ​

finFormSelectBacnetType(folderPath: null) ​

Axon function


meta ​

deffunc:finFormSelectBacnetType
isfunc
liblib:finStackMobile
namefinFormSelectBacnetType
overridable✓
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(folderPath: null) => do
  if(folderPath.isDict)
  do
    if (foilderPath["emptyFolder"] == null)
    do
      if (folderPath["treePath"] != null)
        folderPath = folderPath->treePath
      else folderPath = folderPath["folderPath"]
    end
    else
      folderPath = folderPath["id"]
  end

  if(folderPath == "undefined")
    folderPath = null

  // skip this form and go straight to IP form: FS5-1410
  if (not readAll(ext).any(v => v->ext == "bacnetMstp"))
    return finFormManualAddEditBacnet(null, null, "ip", folderPath)

  body: [
    {
      name: "bacnetType",
      editorType: "combobox",
      dataProvider: "[{dis: \"BacNet IP\", val: \"ip\"}, {dis: \"MSTP\", val: \"mstp\"}]",
      prompt: toLocale("finStackMobileExt::bacnetType"),
      labelField: "dis",
      selectedValueTags: "val"
    },

    {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
    {name: "applyButton", editorType: "button", label: toLocale("finStackExt::next"), controlBar: true}
  ]

  { "dis": toLocale("finStackMobileExt::addBacnetConnector"),
    "name": "finFormSelectBacnetType",
    "body": body.toJSON,
    "cancelButton": "\$cancelButton",
    "commitButton": "\$applyButton",
    "commitAction": "finFormManualAddEditBacnet(null, null, \$bacnetType, "+folderPath.toAxonCode+")",
    "finForm": marker()
  }.toGrid.addMeta({formExecute: marker()})
end


def ​

func:finFormSelectTool ​

finFormSelectTool(id, selected, advanced, reopened: false) ​

Axon function


meta ​

deffunc:finFormSelectTool
isfunc
liblib:finStackMobile
namefinFormSelectTool
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(id, selected, advanced, reopened: false) => do
  treePath: "finFindTools("+selected.toAxonCode+", "+advanced.toAxonCode+")"

  body: [
    {
      name: "toolTree",
      editorType: "ractive",
      ractiveType: "tree",
      prompt: toLocale("finStackMobileExt::dbSelectTool"),
      path: treePath+".map(z => z.merge({icon: `icon-gear`.toStr}))",
      labelField: "treeDisplay",
      selectedValueTags: "name, src",
      tapSelectEnabled: false,
      allowMultiSelect: false,
      height: 450
    },

    { name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true },
    { name: "commitButton", editorType: "button", label: toLocale("finStackMobileExt::dbRunTool"), controlBar: true}
  ]

  if(reopened) body = body.insert(0, {name: "missingMsg", editorType: "label", text: toLocale("finStackMobileExt::dbPleaseSelTool")})

  { "dis":toLocale("finStackMobileExt::dbOpenToolsName"),
    "name": if(not reopened) "finOpenTools" else "finOpenTools" + random(1..10000),
    "body":body.toJSON,
    "width": 450,
    "cancelButton": "\$cancelButton",
    "commitButton":"\$commitButton",
    "commitAction": "if(\$toolTree.isEmpty) finFormSelectTool(@"+id+", "+selected.toAxonCode+", "+advanced+", true) else finRunSelectedTool(@"+id+", "+selected.toAxonCode+", \$toolTree)",
    "finForm": marker()
  }.toGrid.addMeta({formExecute: marker()})
end


def ​

func:finFormSetConnectorDefWriteLevel ​

finFormSetConnectorDefWriteLevel(connectorIds: []) ​

Axon function


meta ​

deffunc:finFormSetConnectorDefWriteLevel
isfunc
liblib:finStackMobile
namefinFormSetConnectorDefWriteLevel
overridable✓
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(connectorIds: []) => do
  defWriteLvl: null

  if (connectorIds.size == 1)
  do
    defWriteLvl = connectorIds.readByIds[0]["defaultWriteLevel"]
  end
  else
  do
    temp: []

    //defWriteLvl =
    connectorIds.readByIds
      .map(r => if(r.has("defaultWriteLevel")) r.set("defaultWriteLevel", r->defaultWriteLevel.toStr) else r.set("defaultWriteLevel", "0"))
      .colToList("defaultWriteLevel")
      .each(x => do
        foundRec: temp.find(v => v->level == x)

        if(foundRec == null)
          temp = temp.add({level: x, count: 1})
        else
          temp = temp.map(r => if(r->level == x) r.set("count", r->count + 1) else r)

        //if(tempDict.has(x)) tempDict = tempDict.map(r => if) .set(x, tempDict[x] + 1) else tempDict.set(x, 1))
      end)
      //echo(temp.toGrid.sort((a,b) => a->count <=> b->count)[0].toAxonCode)

      defWriteLvl = temp.toGrid.sort((a,b) => a->count <=> b->count)[0]->level.parseInt(10, false)
  end

  if(defWriteLvl == null) defWriteLvl = 16

  body: [
    {
      name: "defWriteLevel",
      editorType: "numericstepper",
      prompt: toLocale("finStackMobileExt::defaultWriteLevel"),
      min: 1,
      max: 17,
      defVal: defWriteLvl
    },

    { name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true },
    { name: "applyButton", editorType: "button", label: toLocale("finStackExt::coreApply"), controlBar: true }
  ]

  {
    "dis": toLocale("finStackMobileExt::setDefaultWriteLevel"),
    "name": "finFormSetConnectorDefWriteLevel",
    "body": body.toJSON,
    "cancelButton": "\$cancelButton",
    "commitButton": "\$applyButton",
    "commitAction": "readByIds("+connectorIds.toAxonCode+").toRecList.map(r => r.diff({defaultWriteLevel: \$defWriteLevel})).commit",
    "completeAction": "",
    "finForm": marker()
  }.toGrid.addMeta({formExecute: marker()})
end


def ​

func:finFormSetSummaryPointOrder ​

finFormSetSummaryPointOrder(summaryName, summariesToRunOn: null, pointsInEquip: null, equipFilter: null) ​

Axon function


meta ​

deffunc:finFormSetSummaryPointOrder
isfunc
liblib:finStackMobile
namefinFormSetSummaryPointOrder
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(summaryName, summariesToRunOn:null, pointsInEquip:null, equipFilter:null) => do
  action: "["
  body: [
    {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
    {name: "applyButton",  editorType: "button", label: toLocale("finStackExt::coreApply"),  controlBar: true}
  ]

  if(summaryName.isRef) do
    pointsInEquip = readById(summaryName)

    if(pointsInEquip["pointOrder"] == null) do
      pointsInEquip = parseFilter("("+pointsInEquip->pointFilter+") and point").readAll.unique("navName").colToList("navName")
    end else pointsInEquip = pointsInEquip->pointOrder.split(",")
  end

  pointsInEquip.each((ptName, i) => do
    body = body.add({
      name: ptName.toTagName+"Order",
      editorType: "numericstepper",
      prompt: ptName,
      defVal: i+1
    })

    action = action + "{order: \$"+ptName.toTagName+"Order, name:" + ptName.toAxonCode+"},"
  end)

  action = action[0..-2] + "]"

  { "dis": toLocale("finStackMobileExt::setSummaryPointOrder"),
    "name": "finFormSetSummaryPointOrder",
    "body": body.toJSON,
    "cancelButton": "\$cancelButton",
    "commitButton": "\$applyButton",
    "commitAction": "finFormCreateSummaryApply("+summaryName.toAxonCode+", "+summariesToRunOn.toAxonCode+", "+pointsInEquip.toAxonCode+", "+equipFilter.toAxonCode+", " + action +")",
    "finForm": marker()
  }.toGrid.addMeta({formExecute: marker()})
end


def ​

func:finGetPods ​

finGetPods(podName) ​

Axon function


meta ​

deffunc:finGetPods
isfunc
liblib:finStackMobile
namefinGetPods

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function


def ​

func:finGetPointIcon ​

finGetPointIcon(rec) ​

Returns the name of the appropriate point icon based off the point's type. To be used in the right-side mobile menu.


meta ​

deffunc:finGetPointIcon
isfunc
liblib:finStackMobile
namefinGetPointIcon
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(rec) => do
  if(rec.has("sensor")) "sm-sensor"
  else if(rec.has("cmd")) "sm-command"
  else if(rec.has("sp")) "sm-softpoint"
  else "sm-point"
end


def ​

func:finGetTileOn ​

finGetTileOn(floor) ​

Axon function


meta ​

deffunc:finGetTileOn
isfunc
liblib:finStackMobile
namefinGetTileOn
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(floor) => do
  floor = floor.toRec
  equips: []
  points: []
  tmp: {}

  ioReadJson(`fan://finStackMobileExt/assets/finTiles/finTiles.json`).each x=> try do
    readAll(parseFilter(x->tileOn) and floorRef==floor->id).each y=> try do
      y = y.merge(x).set("dis",y.dis)
      if(y.has("title")) y = y.set("title", y.finMacro(y->title))
      if(y.has("titleEval")) try y = y.set("titleEval", y.set("id", y->id.toAxonCode).finMacro(y->titleEval).eval) catch 0
      equips = equips.add(y)
    end catch 0
  end catch 0

  equips = equips.map(x=> do
    points = []
    x->points.each y=> try do
      if(y.has("query")) do
        x.set("id","@"+x->id).finMacro(y->query).eval.toGrid.each z=> do
          tmp = z.merge(y)
          if(tmp.has("title")) tmp = tmp.set("title", tmp.set("dis",tmp.dis).finMacro(tmp->title))
          points = points.add(tmp)
        end
      end else do
        tmp = read(parseFilter(x.set("id","@"+x->id).finMacro(y->pointFilter)))
        tmp = tmp.merge(y)
        if(tmp.has("title")) tmp = tmp.set("title", tmp.set("dis",tmp.dis).finMacro(tmp->title))
        points = points.add(tmp)
      end
    end catch 0
    x.set("points", points)
  end)

  equips
end


def ​

func:finGraphicTopLevel ​

finGraphicTopLevel(new, data: null) ​

finGraphicTopLevel(new)

Form to create or edit the topLevel record. If the new parameter is true, try to make a new record or edit the existing one. If the new parameter is false, edit the existing one.


meta ​

deffunc:finGraphicTopLevel
isfunc
liblib:finStackMobile
namefinGraphicTopLevel
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(new, data: null) => do
  if(data == null) do
    graphicIndex: 0
    targetIndex: 0
    body: [
      {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
      {name: "commitButton", editorType: "button", label: toLocale("finStackExt::coreApply"), controlBar: true}
    ]

    if(new) do
      if(readCount(topLevel) == 0)
        diff(null, {
          topLevel: marker(),
          dis: toLocale("finStackMobileExt::topLevelDis"),
          finHomePath: "#frame?app=graphics&url=%2Ffin5%2Fdemo%3FprojectRef%3D%401eedac62-ea569755%26title%3DshowSettings"
        }, {add}).commit
      else do
        new = false
        body = body.add({name: "label", editorType: "label", text: toLocale("finStackMobileExt::topLevelExists")})
      end
    end

    rec: read(topLevel)

    if(not new) do
      graphicList: readAll(graphicOn).sort("dis")
      graphicIndex = eachWhile(graphicList) (x, i) => if(rec->finHomePath.contains(x->id.toStr)) i else if(i >= graphicList.size) 0

      if(graphicIndex != null) do
        targetList: readAll(graphicList[graphicIndex]->graphicOn.parseFilter).map(x => x.set("dis", x.dis)).sort("dis")
        targetIndex = eachWhile(targetList) (x, i) => if(rec->finHomePath.contains(x->id.toStr)) i else if(i >= targetList.size) 0
      end else do
        graphicIndex = 0
        targetIndex = 0
      end
    end

    body = body.addAll([
      {
        name: "graphic",
        editorType: "combobox",
        prompt: toLocale("finStackMobileExt::selectGraphic"),
        dataProvider: "readAll(graphicOn).sort(\"dis\")",
        labelField: "dis",
        selectedValueTags: "id",
        defIndex: graphicIndex
      },

      {
        name: "target",
        editorType: "combobox",
        prompt: toLocale("finStackExt::target"),
        dataProvider: "readAll(parseFilter(readById(\$graphic)->graphicOn)).map(x=> if(x.has(\"topLevel\") and not x.has(\"dis\")) x.set(\"dis\", toLocale(\"finStackMobileExt::topLevelDis\")) else x.set(\"dis\",x.dis)).sort(\"dis\")",
        labelField: "dis",
        selectedValueTags: "id",
        defIndex: targetIndex
      }
    ])

    {"dis": if(new) toLocale("finStackMobileExt::createTopLevelRecord") else toLocale("finStackMobileExt::editTopLevelRecord"),
    "name": "finGraphicTopLevel",
    "body": body.toJSON,
    "cancelButton": "\$cancelButton",
    "commitButton": "\$commitButton",
    "commitAction": "finGraphicTopLevel(null, [\$target, \$graphic])",
    "finForm": marker()
    }.toGrid.addMeta({formExecute: marker()})
  end
  else do
    if(read(topLevel)->id == data[0]) do
      read(topLevel).diff({finHomePath: "#frame?app=graphics&url=%2Ffin5%2F"+context()->projName+"%3FprojectRef%3D%40"+data[1]+"%26title%3DshowSettings"}).commit
    end
    else read(topLevel).diff({finHomePath: "#frame?app=graphics&targetRef=@"+data[0]+"&url=%2Ffin5%2F"+context()->projName+"%3FprojectRef%3D%40"+data[1]+"%26title%3DshowSettings%23targetRef%3D%40"+data[0]}).commit
  end
end


def ​

func:finGraphicTopLevelDeleteConfirmForm ​

finGraphicTopLevelDeleteConfirmForm(graphicId, targetRef: null) ​

Axon function


meta ​

deffunc:finGraphicTopLevelDeleteConfirmForm
isfunc
liblib:finStackMobile
namefinGraphicTopLevelDeleteConfirmForm
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(graphicId, targetRef: null) => do
  body: [
    {editorType: "label", text: toLocale("finStackMobileExt::confirmDeleteTopLevelGraphic")},
    {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::no"), controlBar: true},
    {name: "commitButton", editorType: "button", label: toLocale("finStackMobileExt::coreYes"), controlBar: true}
  ]

  {"dis": toLocale("finStackExt::warning"),
  "name": "finGraphicTopLevelDeleteConfirmForm",
  "body": body.toJSON,
  "cancelButton": "\$cancelButton",
  "commitButton": "\$commitButton",
  "commitAction": "readById("+ graphicId.toAxonCode +").diff({trash}).commit", //"finStackMenuDeleteConfirm("+ graphicId.toAxonCode +", \"Graphic\", "+ targetRef.toAxonCode +")",
  "completeAction": "window.app.ObtainMenu(null, null,'graphicsBuilder', " + graphicsMenuSettings(false, null, targetRef).toAxonCode + "); "+
                    "finstack.eval('readAll(imageSlicerImport and graphicRef=="+ graphicId.toAxonCode +").finSoftDelete')",
  "finForm": marker()
  }.toGrid.addMeta({formExecute: marker()})
end


def ​

func:finGraphicsGenericBindings ​

finGraphicsGenericBindings(glist, type) ​

Axon function


meta ​

deffunc:finGraphicsGenericBindings
isfunc
liblib:finStackMobile
namefinGraphicsGenericBindings
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(glist, type) => do
  failed: []
  glist.each g=> do
    f: ""
    names: []
    addeds: []
    try do
      g = readById(g)
      f = toLocale("finStackMobileExt::graphicOnNoMatch")
      id: read(parseFilter(g->graphicOn))->id
      f = toLocale("finStackMobileExt::cannotReadFinFile")
      finfile: g.readFinFile
      f = toLocale("finStackMobileExt::cannotGetPointListForGraphicOn")
      result: finCreateEquipGraphicPointList(id)
      f = toLocale("finStackMobileExt::errorInWriteLoop")
      result.each foliodict=> do
        binding: foliodict->binding
        dis: foliodict->dis
        refKind: foliodict->refKind
        navdisp: foliodict->display
        if(navdisp.startsWith("(ahuRef) ")) navdisp = navdisp[9..-1]
        finfile = finfile.map(vpoint=> do
          if(vpoint.has("binding") and vpoint.has("virtualPoint") and not vpoint.has("targetPoint")) do
            if(names.index(vpoint->displayName) == null) names = names.add(vpoint->displayName)
            if(vpoint->displayName == dis) do
              if(addeds.index(vpoint->displayName) == null) addeds = addeds.add(vpoint->displayName)
              if(type == "nav") vpoint = vpoint.set("binding", "equipRef==\$"+refKind+" and navName==\""+navdisp+"\"")
              else if(type == "rel") vpoint = vpoint.set("binding", "equipRef==\$"+refKind+" and "+binding)
            end
          end
          vpoint
        end)
      end
      f = toLocale("finStackMobileExt::cannotWriteFinFile")
      finfile.writeFinFile(g->id)
      f = ""
    end catch failed = failed.add([g.toRec.dis, f])
    addeds.each x=> names = names.remove(names.index(x))
    names.each x=> failed = failed.add([g.toRec.dis, toLocale("finStackMobileExt::bindingForGraphicNoUpdated").replace("{graphicName}", x)])
  end
  finGraphicsGenericBindingsResults(failed)
end


def ​

func:finGraphicsGenericBindingsForm ​

finGraphicsGenericBindingsForm(tref: null) ​

Axon function


meta ​

deffunc:finGraphicsGenericBindingsForm
isfunc
liblib:finStackMobile
namefinGraphicsGenericBindingsForm
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(tref: null) => do
  if(tref == null) dp: "readAll(graphicOn).findAll(x=> try do parseFilter(x->graphicOn); true end catch false)"
  else dp: "readAll(graphicOn).findAll(x=> try readAll(id=="+ tref.toAxonCode +").finGridFilter(parseFilter(x->graphicOn)).size > 0 catch false)"

  body: [
  {name: "gList", editorType: "list", prompt: toLocale("finStackMobileExt::graphicUDBinding"), defIndex: 0, listType: "checkbox",
    dataProvider: dp+".sort(\"dis\")", labelField: "dis", selectedValueTags: "id", height: 150},
  {name: "type", editorType: "radio", label: toLocale("finStackMobileExt::coreRelative"), selectedValue: "rel", defVal: true},
  {name: "type", editorType: "radio", label: toLocale("finStackMobileExt::navName"), selectedValue: "nav"},
  {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
  {name: "commitButton", editorType: "button", label: toLocale("finStackExt::builderUpdate"), controlBar: true}
  ]

  {"dis": toLocale("finStackExt::updateBindings"),
  "name": "finGraphicsGenericBindingsForm",
  "body": body.toJSON,
  "cancelButton": "\$cancelButton",
  "commitButton": "\$commitButton",
  "commitAction": "finGraphicsGenericBindings(\$gList, \$type)",
  "finForm": marker()
  }.toGrid.addMeta({formExecute: marker()})
end

//read(graphicOn).readFinFile.finGridFilter(virtualPoint and binding and not targetPoint) //finGetVirtualPoints
//selected thing //finGetTargetPoint


def ​

func:finGraphicsGenericBindingsResults ​

finGraphicsGenericBindingsResults(fail) ​

Axon function


meta ​

deffunc:finGraphicsGenericBindingsResults
isfunc
liblib:finStackMobile
namefinGraphicsGenericBindingsResults
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(fail) => do
  failed: true
  body: [
  {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::ok"), controlBar: true}
  ]

  if(fail.size == 0) do
    failed = false
    body = body.add({name: "label", editorType: "label", text: toLocale("finStackMobileExt::allBindingsUpdated")})
  end else do
    fail = fail.map(y=> {g: y[0], v: y[1]}).toGrid
    y: fail.unique("g").colToList("g")
    y.each z=> do
      m: ""
      body = body.add({name: "label", editorType: "label", text: z+":"})
      fail.findAll(n=> n->g==z).each n=> m = m+n->v+"\n"
      body = body.add({name: "textarea", editorType: "textarea", defVal: m, editable: false, height: 100})
      body = body.add({name: "label", editorType: "label", text: "----------------------"})
    end
    body = body[0..-2]
  end

  {"dis": if(failed) toLocale("finStackMobileExt::uDBindingsFailures") else toLocale("finStackExt::bLineSuccess"),
  "name": "finGraphicsGenericBindingsResults",
  "body": body.toJSON,
  "cancelButton": "\$cancelButton",
  "commitButton": "\$commitButton",
  "commitAction": "null",
  "finForm": marker()
  }.toGrid.addMeta({formExecute: marker()})
end


def ​

func:finGraphicsUpdateThumbs ​

finGraphicsUpdateThumbs(stage: null, data: null) ​

Form to change the thumbnails on graphics


meta ​

deffunc:finGraphicsUpdateThumbs
isfunc
liblib:finStackMobile
namefinGraphicsUpdateThumbs
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(stage: null, data: null) => do
  if(stage == null) do
    body: [
      {
        name: "list",
        editorType: "list",
        prompt: toLocale("finStackExt::rightMenuGraphicsTitle"),
        dataProvider: "readAll(fin5 and not finTemplate).sort(\"dis\")",
        labelField: "dis",
        selectedValueTags: "id",
        height: 200,
        listType: "checkbox"
      },

      {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
      {name: "commitButton", editorType: "button", label: toLocale("finStackExt::next"), controlBar: true}
    ]

    {"dis": toLocale("finStackMobileExt::graphicUDThumbs"),
    "name": "finGraphicsUpdateThumbs",
    "body": body.toJSON,
    "cancelButton": "\$cancelButton",
    "commitButton": "\$commitButton",
    "commitAction": "finGraphicsUpdateThumbs(\$list)",
    "finForm": marker()
    }.toGrid.addMeta({formExecute: marker()})
  end
  else if(stage.isList) do
    if(data != null) do
      if(data->reuse == true) data->id.readById.diff({thumbnail: data->combo}).commit
      else if(data->file != "") data->id.readById.diff({thumbnail: data->file}).commit
    end

    if(stage.size > 0) do
      if(stage.size == 1)
        word: toLocale("finStackMobileExt::folioRestoreFinished")
      else
        word: toLocale("finStackExt::next")

      body: [
        {
          name: "label",
          editorType: "label",
          prompt: toLocale("finStackMobileExt::gbGraphic"),
          text: stage[0].readById.dis
        },

        {
          name: "file",
          editorType: "file",
          prompt: toLocale("finStackMobileExt::selectNewImage"),
          fileTypes: ["jpg","png","gif","bmp","tif"],
          tags: {thumbnail}
        },

        {
          name: "combo",
          editorType: "combobox",
          prompt: toLocale("finStackMobileExt::selectExistingImage"),
          labelField: "dis",
          selectedValueTags: "id",
          dataProvider: "readAll(file).findAll(x=> x->file.toStr.contains(\"image\")).sort(\"dis\")"
        },

        {
          name: "reuse",
          editorType: "checkbox",
          prompt: toLocale("finStackExt::omMenuUseExisting")
        },

        {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
        {name: "commitButton", editorType: "button", label: word, controlBar: true}
      ]

      {"dis": toLocale("finStackMobileExt::graphicUDThumbs"),
      "name": "finGraphicsUpdateThumbs2",
      "body": body.toJSON,
      "cancelButton": "\$cancelButton",
      "commitButton": "\$commitButton",
      "commitAction": "finGraphicsUpdateThumbs("+stage[1..-1].toAxonCode+", {id: @"+stage[0]+", file: \$file, combo: \$combo,reuse:\$reuse})",
      "finForm": marker()
      }.toGrid.addMeta({formExecute: marker()})
    end
  end
end


def ​

func:finHasSpecialChars ​

finHasSpecialChars(stringToCheck) ​

Axon function


meta ​

deffunc:finHasSpecialChars
isfunc
liblib:finStackMobile
namefinHasSpecialChars
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function


def ​

func:finHeaderAddEditMenu ​

finHeaderAddEditMenu(idnex: null) ​

Axon function


meta ​

deffunc:finHeaderAddEditMenu
isfunc
liblib:finStackMobile
namefinHeaderAddEditMenu
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(idnex: null) => do
  header: read(finHeader)
  oidnex: idnex
  try itm: header->buttons.fromJSON[idnex] catch do
    btns: header->buttons.fromJSON.add({icon: "icon-plus", iconType: "icon", label: toLocale("finStackMobileExt::bLineNew"), link: "null", linkType: "action", open: false}).toJSON
    header = read(finHeader).diff({buttons: btns}).commit
    idnex = header->buttons.fromJSON.size - 1
    itm: header->buttons.fromJSON[idnex]
  end

  pointVars: g => [
    {
      label: toLocale("finStackExt::coreEdit"),
      icon: "icon-pencil",
      action: "finHeaderAddEditSubMenu("+idnex+","+g+")",
      keepOpen: true
    },
    {
      label: toLocale("finStackExt::remove"),
      icon: "icon-trash",
      style: "background-color: red",
      action: "read(finHeader).diff({buttons:read(finHeader)->buttons.fromJSON.set("+idnex+",read(finHeader)->buttons.fromJSON["+idnex+"].set(\"children\",read(finHeader)->buttons.fromJSON["+idnex+"]->children.remove("+g+"))).toJSON}).commit",
      refresh: "finHeaderAddEditMenu("+idnex+")",
      keepOpen: true
    }
  ]

  list: [
    {
      displayName: "— " + (if(oidnex == null) toLocale("finStackExt::add") else toLocale("finStackExt::coreEdit")) + " " + toLocale("finStackMobileExt::gbHyperButton") + " —",
      isHeader: true,
      primaryHeader: true,
      isDivider: true,
      order: -9999
    }, {
      displayName: toLocale("finStackMobileExt::setDisplayName"),
      appId: "header",
      action: "finHeaderButtonNameForm("+idnex+")",
      finForm: true,
      icon: "icon-pencil",
      iconType: "class",
      keepOpen: true,
      ui: "html",
      minUiTarget: "phone",
      order: 1
    },{
      displayName: toLocale("finStackMobileExt::setIcon"),
      appId: "header",
      ignoreSettings: marker(),
      action: "finHeaderButtonIconForm("+idnex+")",
      finForm: true,
      icon: "icon-photo",
      iconType: "class",
      keepOpen:true,
      ui: "html",
      minUiTarget: "phone",
      order: 2
    },{
      displayName: toLocale("finStackMobileExt::addSecurityTags"),
      appId: "header",
      ignoreSettings: marker(),
      action: "finHeaderButtonSecurityForm("+idnex+")",
      finForm: true,
      icon: "icon-tag",
      iconType: "class",
      keepOpen:true,
      ui: "html",
      minUiTarget: "phone",
      order: 3
    },{
      displayName: toLocale("finStackMobileExt::setBadge"),
      appId: "header",
      ignoreSettings: marker(),
      action: "finHeaderButtonBadgeForm("+idnex+")",
      finForm: true,
      icon: "icon-information",
      iconType: "class",
      keepOpen:true,
      ui: "html",
      minUiTarget: "phone",
      order: 4
    },{
      displayName: toLocale("finStackMobileExt::setLink"),
      appId: "header",
      ignoreSettings: marker(),
      action: "finHeaderButtonLinkForm("+idnex+")",
      finForm: true,
      icon: "icon-web",
      iconType: "class",
      keepOpen:true,
      ui: "html",
      minUiTarget: "phone",
      order: 5
    },{
      displayName: toLocale("finStackMobileExt::addSubmenuButton"),
      appId: "header",
      ignoreSettings: marker(),
      action: "finHeaderAddEditSubMenu("+idnex+")",
      icon: "icon-plus",
      iconType: "class",
      keepOpen:true,
      ui: "html",
      minUiTarget: "phone",
      order: 6
    }
  ]

  if(itm.has("children") and itm->children.size > 0) do
    list = list.addAll([{
      displayName: toLocale("finStackMobileExt::reorderSubmenuButtons"),
      appId: "header",
      ignoreSettings: marker(),
      action: "finHeaderReorderSubMenu("+idnex+")",
      icon: "icon-list",
      iconType: "class",
      keepOpen:true,
      ui: "html",
      minUiTarget: "phone",
      order: 7
    },{
      displayName: toLocale("finStackMobileExt::submenuButtons"),
      secondaryHeader: true,
      isDivider: true,
      ignoreSettings,
      order: 8
    }])
    order: 0
    header->buttons.fromJSON[idnex]->children.each x=> do
      list = list.add({
        displayName: x->label,
        appId: "header",
        ignoreSettings: marker(),
        action: "null",
        icon: x->icon,
        iconType: "class",
        keepOpen:true,
        ui: "html",
        minUiTarget: "phone",
        order: order + 9,
        submenu: pointVars(order)
      })
      order = order + 1
    end
  end

  list.add({
    displayName: toLocale("finStackExt::back"),
    icon: "icon-return",
    iconType: "class",
    keepOpen: true,
    action: "finHeaderMenu()",
    order: -1100,
    level: 0,
    ignoreSettings: marker(),
  })
end


def ​

func:finHeaderAddEditSubMenu ​

finHeaderAddEditSubMenu(parnt: null, idnex: null) ​

Axon function


meta ​

deffunc:finHeaderAddEditSubMenu
isfunc
liblib:finStackMobile
namefinHeaderAddEditSubMenu
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(parnt: null, idnex: null) => do
  header: read(finHeader)
  mainbutn: header->buttons.fromJSON[parnt]
  oidnex: idnex

  try
    itm: mainbutn->children[idnex]
  catch
  do
    itm: {
      icon: "icon-plus",
      iconType: "icon",
      label: toLocale("finStackMobileExt::bLineNew"),
      link: "null",
      linkType: "action"
    }

    if(not mainbutn.has("children")) mainbutn = mainbutn.set("children", [itm])
    else mainbutn = mainbutn.set("children", mainbutn->children.add(itm))

    btns: header->buttons.fromJSON.set(parnt, mainbutn).toJSON
    header = read(finHeader).diff({buttons: btns}).commit
    idnex = mainbutn->children.size - 1
  end
  [
    {
      displayName: "— " + (if(oidnex == null) toLocale("finStackExt::weatherMenuAdd") else toLocale("finStackExt::coreEdit")) + " " + toLocale("finStackMobileExt::gbHyperButton") + " —",
      primaryHeader: true,
      isDivider: true,
      ignoreSettings,
      order: -9999
    },{
      displayName: toLocale("finStackMobileExt::setDisplayName"),
      appId: "header",
      ignoreSettings: marker(),
      action: "finHeaderButtonNameForm("+parnt+","+idnex+")",
      finForm: true,
      icon: "icon-pencil",
      iconType: "class",
      keepOpen: true,
      ui: "html",
      minUiTarget: "phone",
      order: 1
    },{
      displayName: toLocale("finStackMobileExt::setIcon"),
      appId: "header",
      ignoreSettings: marker(),
      action: "finHeaderButtonIconForm("+parnt+","+idnex+")",
      finForm: true,
      icon: "icon-photo",
      iconType: "class",
      keepOpen:true,
      ui: "html",
      minUiTarget: "phone",
      order: 2
    },{
      displayName: toLocale("finStackMobileExt::setBadge"),
      appId: "header",
      ignoreSettings: marker(),
      action: "finHeaderButtonBadgeForm("+parnt+","+idnex+")",
      finForm: true,
      icon: "icon-information",
      iconType: "class",
      keepOpen:true,
      ui: "html",
      minUiTarget: "phone",
      order: 4
    },{
      displayName: toLocale("finStackMobileExt::setLink"),
      appId: "header",
      ignoreSettings: marker(),
      action: "finHeaderButtonLinkForm("+parnt+","+idnex+")",
      finForm: true,
      icon: "icon-web",
      iconType: "class",
      keepOpen:true,
      ui: "html",
      minUiTarget: "phone",
      order: 5
    },
    {
      displayName: toLocale("finStackExt::back"),
      icon: "icon-return",
      iconType: "class",
      keepOpen: true,
      action: "finHeaderAddEditMenu("+parnt+")",
      order: -1100,
      level: 0,
      ignoreSettings: marker(),
    }
  ]
end


def ​

func:finHeaderButtonBadgeForm ​

finHeaderButtonBadgeForm(parnt, child: null) ​

Axon function


meta ​

deffunc:finHeaderButtonBadgeForm
isfunc
liblib:finStackMobile
namefinHeaderButtonBadgeForm
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(parnt, child: null) => do
  header: read(finHeader)
  butn: header->buttons.fromJSON[parnt]
  if(child != null) butn = butn->children[child]

  body: [
    {
      name:"bqu",
      editorType:"textinput",
      prompt:toLocale("finStackMobileExt::badgeQuery"),
      defVal:try butn->badgeQuery catch ""
    },

    {
      name:"bcl",
      editorType:"combobox",
      prompt:toLocale("finStackMobileExt::badgeClass"),
      dataProvider:"[\"none\",\"success\",\"error\",\"focus\"]",
      labelField:"val",
      selectedValueTags:"val",
      defIndex: if(butn.has("badgeClass")) ["none","success","error","focus"].index(butn->badgeClass) else 0
    },

    {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
    {name: "commitButton", editorType: "button", label: toLocale("finStackExt::coreApply"), controlBar: true}
  ]

  if(child == null) do
    comact: "read(finHeader).diff({buttons: read(finHeader)->buttons.fromJSON.set("+parnt+",read(finHeader)->buttons.fromJSON["+parnt+"].set(\"badgeQuery\",\$bqu).set(\"badgeClass\",\$bcl)).toJSON}).commit"
  end else do
    comact: "read(finHeader).diff({buttons:read(finHeader)->buttons.fromJSON.set("+parnt+",read(finHeader)->buttons.fromJSON["+parnt+"].set(\"children\",read(finHeader)->buttons.fromJSON["+parnt+"]->children.set("+child+",read(finHeader)->buttons.fromJSON["+parnt+"]->children["+child+"].set(\"badgeQuery\",\$bqu).set(\"badgeClass\",\$bcl)))).toJSON}).commit"
  end

  {
    "dis": toLocale("finStackMobileExt::editButtonBadge"),
    "name": "finHeaderButtonBadgeForm",
    "body": body.toJSON,
    "cancelButton": "\$cancelButton",
    "commitButton": "\$commitButton",
    "commitAction": comact,
    "finForm": marker()
  }.toGrid.addMeta({formExecute: marker()})
end


def ​

func:finHeaderButtonIconForm ​

finHeaderButtonIconForm(parnt, child: null, data: null) ​

Axon function


meta ​

deffunc:finHeaderButtonIconForm
isfunc
liblib:finStackMobile
namefinHeaderButtonIconForm
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(parnt, child: null, data: null) => do
  header: read(finHeader)
  butn: header->buttons.fromJSON[parnt]
  if(child != null) butn = butn->children[child]

  if(data == null) do
    body: [
      {
        name:"ico",
        editorType: "ractive",
        ractiveType: "multiselect",
        prompt: toLocale("finStackExt::finIcon"),
        data: finGetIconMultiSelectData(),
        autoClose: true,
        selectedValueTags: "icon",
        singleSelect: true
      },

      {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
      {name: "commitButton", editorType: "button", label: toLocale("finStackExt::coreApply"), controlBar: true}
    ]

    {"dis": toLocale("finStackMobileExt::editButtonIcon"),
    "name": "finHeaderButtonIconForm",
    "body": body.toJSON,
    "cancelButton": "\$cancelButton",
    "commitButton": "\$commitButton",
    "commitAction": "finHeaderButtonIconForm("+parnt+","+child+",\$ico)",
    "finForm": marker()
    }.toGrid.addMeta({formExecute: marker()})
  end else do
    if(data.size > 0) do
      butn = butn.set("icon", data[0]->icon)
      if(child == null) read(finHeader).diff({buttons: read(finHeader)->buttons.fromJSON.set(parnt, butn).toJSON}).commit
      else do
        mainbutns: header->buttons.fromJSON
        mainbutns = mainbutns.set(parnt, mainbutns[parnt].set("children",mainbutns[parnt]->children.set(child, butn)))
        read(finHeader).diff({buttons: mainbutns.toJSON}).commit
      end
    end
  end
end


def ​

func:finHeaderButtonLinkForm ​

finHeaderButtonLinkForm(parnt, child: null, data: null) ​

Axon function


meta ​

deffunc:finHeaderButtonLinkForm
isfunc
liblib:finStackMobile
namefinHeaderButtonLinkForm
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(parnt, child: null, data: null) => do
  header: read(finHeader)
  butn: header->buttons.fromJSON[parnt]
  if(child != null) butn = butn->children[child]
  lntypes: ["action","hash","url","Graphic"].map((x,y)=> {a:x, b:y})

  if(data == null) do
    body: [
      {name:"lnk",editorType:"textinput",prompt:toLocale("finStackMobileExt::link"),defVal:try butn->link catch "#"},//link
      {name:"lnt",editorType:"combobox",prompt:toLocale("finStackMobileExt::linkType"),dataProvider:lntypes.toAxonCode,labelField:"a",selectedValueTags:"b",
        defIndex: try lntypes.find(x=> x->a == butn->linkType)->b catch 3},//lntype

      {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
      {name: "commitButton", editorType: "button", label: toLocale("finStackExt::coreApply"), controlBar: true}
    ]

    {
      "dis": toLocale("finStackMobileExt::editButtonLink"),
      "name": "finHeaderButtonLinkForm",
      "body": body.toJSON,
      "cancelButton": "\$cancelButton",
      "commitButton": "\$commitButton",
      "commitAction": "finHeaderButtonLinkForm("+parnt+","+child+",[\$lnk,\$lnt])",
      "finForm": marker()
    }.toGrid.addMeta({formExecute: marker()})
  end
  else do
    if(data[1] != 3) do
      ltype: lntypes[data[1]]->a
      butn = butn.set("link",data[0]).set("linkType",ltype)
      if(child == null) read(finHeader).diff({buttons: header->buttons.fromJSON.set(parnt, butn).toJSON}).commit
      else do
        mainbutns: header->buttons.fromJSON
        mainbutns = mainbutns.set(parnt, mainbutns[parnt].set("children",mainbutns[parnt]->children.set(child, butn)))
        read(finHeader).diff({buttons: mainbutns.toJSON}).commit
      end
    end else do
      body: [
        {
          name:"grph",
          editorType:"combobox",
          prompt:toLocale("finStackMobileExt::chooseGraphic"),
          dataProvider:"readAll(fin5).sort((x,y)=> x.dis<=>y.dis)",
          labelField:"dis",
          selectedValueTags:"id",
          defIndex:0
        },

        {
          name:"targ",
          editorType:"list",
          prompt:toLocale("finStackMobileExt::chooseTarget"),
          labelField:"dis",
          selectedValueTags:"id",
          dataProvider:"readById(\$grph)->graphicOn.parseFilter.readAll.sort((x,y)=> x.dis<=>y.dis)",
          listType:"checkbox"
        },

        {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
        {name: "commitButton", editorType: "button", label: toLocale("finStackExt::coreApply"), controlBar: true}
      ]

      if(data.size > 2 and data[2] == true) body = body.insert(0,{name:"label",editorType:"label",text:toLocale("finStackMobileExt::pickTarget")})

      {
        "dis": toLocale("finStackMobileExt::editButtonLinkGraphic"),
        "name": "finHeaderButtonLinkForm"+random(0..10000),
        "body": body.toJSON,
        "cancelButton": "\$cancelButton",
        "commitButton": "\$commitButton",
        "commitAction": "if(size(\$targ)>0) finHeaderButtonLinkForm("+parnt+","+child+",[\"#frame?app=graphics&targetRef=@\"+(\$targ[0])+\"&url=%2Ffin5%2F"+context()->projName+"%3FprojectRef%3D%40\"+\$grph+\"%26title%3DshowSettings%23targetRef%3D%40\"+(\$targ[0]),1]) else finHeaderButtonLinkForm("+parnt+","+child+",[\"\",3,true])",
        "finForm": marker()
      }.toGrid.addMeta({formExecute: marker()})
    end
  end
end


def ​

func:finHeaderButtonNameForm ​

finHeaderButtonNameForm(parnt, child: null) ​

Axon function


meta ​

deffunc:finHeaderButtonNameForm
isfunc
liblib:finStackMobile
namefinHeaderButtonNameForm
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(parnt, child: null) => do
  header: read(finHeader)
  butn: header->buttons.fromJSON[parnt]
  if(child != null) butn = butn->children[child]

  body: [
    {name: "name", editorType: "textinput", prompt: toLocale("finStackMobileExt::hostDisplayName"), defVal: butn->label},
    {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
    {name: "commitButton", editorType: "button", label: toLocale("finStackExt::coreApply"), controlBar: true}
  ]

  if (child == null) do
    refreshact: "finstack.eval('finHeaderAddEditMenu("+parnt.toAxonCode+")').then(grid => app.findComponent('settings').set({settings: grid.result.toObj()}))"
    comact: "read(finHeader).diff({buttons:read(finHeader)->buttons.fromJSON.set("+parnt+",read(finHeader)->buttons.fromJSON["+parnt+"].set(\"label\",\$name)).toJSON}).commit"
  end else do
    refreshact: "finstack.eval('finHeaderAddEditSubMenu("+parnt+","+child+")').then(grid => app.findComponent('settings').set({settings: grid.result.toObj()}))"
    comact: "read(finHeader).diff({buttons:read(finHeader)->buttons.fromJSON.set("+parnt+",read(finHeader)->buttons.fromJSON["+parnt+"].set(\"children\",read(finHeader)->buttons.fromJSON["+parnt+"]->children.set("+child+",read(finHeader)->buttons.fromJSON["+parnt+"]->children["+child+"].set(\"label\",\$name)))).toJSON}).commit"
  end

  {"dis": toLocale("finStackMobileExt::editButtonName"),
  "name": "finHeaderButtonNameForm",
  "body": body.toJSON,
  "cancelButton": "\$cancelButton",
  "commitButton": "\$commitButton",
  "commitAction": comact,
  "completeAction": refreshact,
  "finForm": marker()
  }.toGrid.addMeta({formExecute: marker()})
end


def ​

func:finHeaderButtonSecurityForm ​

finHeaderButtonSecurityForm(parnt, child: null) ​

Axon function


meta ​

deffunc:finHeaderButtonSecurityForm
isfunc
liblib:finStackMobile
namefinHeaderButtonSecurityForm
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(parnt, child: null) => do
  header: read(finHeader)
  butn: header->buttons.fromJSON[parnt]

  body: [
    {
      name: "tags",
      editorType: "textinput",
      prompt: toLocale("finStackMobileExt::securityTags"),
      defVal: try butn->buttonTags catch ""
    },

    {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
    {name: "commitButton", editorType: "button", label: toLocale("finStackExt::coreApply"), controlBar: true}
  ]

  if(child == null) do
    comact: "read(finHeader).diff({buttons:read(finHeader)->buttons.fromJSON.set("+parnt+",read(finHeader)->buttons.fromJSON["+parnt+"].set(\"buttonTags\",\$tags.split(\",\").map(x=> if(x.trim == \"\") \"\" else x.toTagName).concat(\",\"))).toJSON}).commit"
  end else do
    comact: ""
  end

  {
    "dis": toLocale("finStackMobileExt::editButtonSecurityTags"),
    "name": "finHeaderButtonSecurityForm",
    "body": body.toJSON,
    "cancelButton": "\$cancelButton",
    "commitButton": "\$commitButton",
    "commitAction": comact,
    "finForm": marker()
  }.toGrid.addMeta({formExecute: marker()})
end


def ​

func:finHeaderForm ​

finHeaderForm(stage: null, data: null) ​

Axon function


meta ​

deffunc:finHeaderForm
deprecated✓
isfunc
liblib:finStackMobile
namefinHeaderForm
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(stage: null, data: null) => do
  r:(g)=> g.fromJSON
  finHeaderFuncs()
  rec: read(finHeader)
  if(not rec.has("buttons") or (try not rec->buttons.r.isList catch true)) rec = rec.set("buttons", "[]")
  try stage = stage.toStr.parseInt catch stage = null
  query: { "name": "finHeaderForm"+random(0..10000),"finForm": marker(),
    "cancelButton": "\$cancelButton","commitButton": "\$commitButton" }
  f:(g,h,i)=> g.set("dis",h).set("body",i.toJSON).toGrid.addMeta({formExecute: marker()})

  if(stage == null) finHeaderFuncs(0)
  else if(stage == 2) do
    butns: rec->buttons.r
    cou: -1
    butns = butns.map((x,y)=> {label: x->label, num: y}).insert(0,{label:"",num: -1}).toAxonCode
    body: [
      {name: "butn", editorType: "combobox", prompt: toLocale("finStackMobileExt::selectButton"), dataProvider: butns, labelField: "label", selectedValueTags: "num", defIndex: 0},
      {name: "opt", editorType: "radio", prompt: toLocale("finStackMobileExt::buttonOptions"), label: toLocale("finStackMobileExt::addButton"), selectedValue: 3, defVal: true},
      {name: "opt", editorType: "radio", label: toLocale("finStackMobileExt::removeButton"), selectedValue: 4},
      {name: "opt", editorType: "radio", label: toLocale("finStackMobileExt::editButton"), selectedValue: 5},
      {name: "opt", editorType: "radio", label: toLocale("finStackMobileExt::reorderButtons"), selectedValue: 6},
      {name: "sep", editorType: "separator"},
      {name: "subm", editorType: "combobox", prompt: toLocale("finStackMobileExt::selectSubmenu"), labelField: "label", selectedValueTags: "num", defIndex: 0,
        dataProvider: "if(\$butn >= 0) try read(finHeader)->buttons.fromJSON[\$butn]->children.map((x,y)=> {label: x->label, num: y}) catch [] else []"},
      {name: "opt", editorType: "radio", prompt: toLocale("finStackMobileExt::subMenuOptions"), label: toLocale("finStackMobileExt::addSubmenuItem"), selectedValue: 7},
      {name: "opt", editorType: "radio", label: toLocale("finStackMobileExt::removeSubmenuItem"), selectedValue: 8},
      {name: "opt", editorType: "radio", label: toLocale("finStackMobileExt::editSubmenuItem"), selectedValue: 9},
      {name: "opt", editorType: "radio", label: toLocale("finStackMobileExt::reorderSubmenuItems"), selectedValue: 10},
      {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::done"), controlBar: true},
      {name: "commitButton", editorType: "button", label: toLocale("finStackExt::next"), controlBar: true}
    ]

    if(data.isStr)
      body = body.insert(0, {name: "label", editorType: "label", prompt: toLocale("finStackMobileExt::reportColStatus")+":", text: "*** "+data+" ***"})

    query.set("commitAction", "finHeaderForm(\$opt, [\$butn, \$subm])").f("Header Menu", body)
  end
  else if(stage == 3 or stage == 5) do //add/edit button
    if(data[0] != -2) do
      if(stage == 3) do
        data = finHeaderFuncs(3)
        rec = data[0]; data = [data[1]]
      end; b: rec->buttons.r[data[0]]

      body: [
        {
          name:"lab",
          editorType:"textinput",
          prompt:toLocale("finStackMobileExt::hostDisplayName"),
          defVal:b->label
        },
        {
          name:"ico",
          editorType: "ractive",
          ractiveType: "multiselect",
          prompt: toLocale("finStackExt::finIcon"),
          data: finGetIconMultiSelectData(),
          autoClose: true,
          selectedValueTags: "icon"
        },

        {
          name:"tgs",
          editorType:"textinput",
          prompt:toLocale("finStackMobileExt::securityTags"),
          defVal: try b->buttonTags catch ""
        },

        {name: "sep", editorType: "separator"},

        {
          name:"bqu",
          editorType:"textinput",
          prompt:toLocale("finStackMobileExt::badgeQuery"),
          defVal:try b->badgeQuery catch ""
        },//bquery

        {
          name:"bcl",
          editorType:"combobox",
          prompt:toLocale("finStackMobileExt::badgeClass"),
          dataProvider:"[\"none\",\"success\",\"error\",\"focus\"]",
          labelField:"val",
          selectedValueTags:"val",
          defIndex: if(b.has("badgeClass")) ["none","success","error","focus"].index(b->badgeClass) else 0},//bclass

        {name: "sep", editorType: "separator"},

        {
          name:"lnk",
          editorType:"textinput",
          prompt:toLocale("finStackMobileExt::link"),
          defVal:try b->link catch ""
        },//link

        {
          name:"lnt",
          editorType:"combobox",
          prompt:toLocale("finStackMobileExt::linkType"),
          dataProvider:finHeaderFuncs(11).toAxonCode,
          labelField:"val",
          selectedValueTags:"val",
          defIndex: if(b.has("linkType")) finHeaderFuncs(11).index(b->linkType) else 1
        },//lntype

        {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
        {name: "commitButton", editorType: "button", label: toLocale("finStackExt::next"), controlBar: true}
      ]

      query.set("commitAction", "finHeaderForm(5, [-2, ["+data[0]+", \$lab, \$ico, \$bqu, \$bcl, \$lnk, \$lnt, \$tgs]])").f(toLocale("finStackMobileExt::editButton"), body)
    end else finHeaderFuncs(stage, data)
  end
  else if(stage == 4) do //remove button
    finHeaderFuncs(stage, data)
  end
  else if(stage == 6) do //reorder buttons
    if(data[0] != -2) do
      body: [{name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
      {name: "commitButton", editorType: "button", label: toLocale("finStackExt::next"), controlBar: true}]

      cou: 0; cact: "finHeaderForm(6, [-2, [{a:"
      rec->buttons.r.each x=> do
        body = body.add({name: cou+"asdf", editorType: "numericstepper", prompt: "Order for: "+x->label, defVal: cou, minVal: 0})
        cact = cact+cou+",b:\$"+cou+"asdf},{a:"
        cou = cou + 1
      end; cact = cact[0..-5]+"].sort((x,y)=> x->b <=> y->b)])"

      query.set("commitAction", cact).f(toLocale("finStackMobileExt::reorderButtons"), body)
    end else finHeaderFuncs(stage, data)
  end
  else if(stage == 7 or stage == 9) do //add/edit submenu button
    if(data[0] != -2) do
      if(data[0] != -1) do
        if(stage == 7 or data.size == 1 or data[1].isList) do
          data = finHeaderFuncs(7, data)
          rec = data[0]; data = [data[2], data[1]]
        end; s: rec->buttons.r[data[0]]->children[data[1]]

        body: [
          {name:"lab",editorType:"textinput",prompt:toLocale("finStackMobileExt::hostDisplayName"),defVal:s->label},
          {
            name:"ico",
            editorType: "ractive",
            ractiveType: "multiselect",
            prompt: toLocale("finStackExt::finIcon"),
            data: finGetIconMultiSelectData(),
            autoClose: true,
            selectedValueTags: "icon"
          },
          {name: "sep", editorType: "separator"},

          {name:"bqu",editorType:"textinput",prompt:toLocale("finStackMobileExt::badgeQuery"),defVal:try s->badgeQuery catch ""},//bquery
          {name:"bcl",editorType:"combobox",prompt:toLocale("finStackMobileExt::badgeClass"),dataProvider:"[\"none\",\"success\",\"error\",\"focus\"]",labelField:"val",
            selectedValueTags:"val",defIndex: if(s.has("badgeClass")) ["none","success","error","focus"].index(s->badgeClass) else 0},//bclass

          {name: "sep", editorType: "separator"},

          {name:"lnk",editorType:"textinput",prompt:toLocale("finStackMobileExt::link"),defVal:try s->link catch ""},//link
          {name:"lnt",editorType:"combobox",prompt:toLocale("finStackMobileExt::linkType"),dataProvider:finHeaderFuncs(11).toAxonCode,labelField:"val",selectedValueTags:"val",
            defIndex: if(s.has("linkType")) finHeaderFuncs(11).index(s->linkType) else 1},//lntype

          {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
          {name: "commitButton", editorType: "button", label: toLocale("finStackExt::next"), controlBar: true}
        ]

        query.set("commitAction", "finHeaderForm(9, [-2, ["+data[0]+","+data[1]+", \$lab, \$ico, \$bqu, \$bcl, \$lnk, \$lnt]])").f(toLocale("finStackMobileExt::editSubmenuButton"), body)
      end else finHeaderForm(2, toLocale("finStackMobileExt::noMenuButtonSel"))
    end else finHeaderFuncs(stage, data)
  end
  else if(stage == 8) do //remove submenu button
    finHeaderFuncs(stage, data)
  end
  else if(stage == 10) do //reorder submenu buttons
    if(data[0] != -2) do
      if(data[0] != -1) do
        if(data.size > 1 and not data[1].isList) do
          body: [{name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
          {name: "commitButton", editorType: "button", label: toLocale("finStackExt::next"), controlBar: true}]

          cou: 0; cact: "finHeaderForm(10, [-2, ["+data[0]+",{a:"
          btns: rec->buttons.r[data[0]]->children
          btns.each x=> do
            body = body.add({name: cou+"asdf", editorType: "numericstepper", prompt: toLocale("finStackMobileExt::orderFor") + ": "+x->label, defVal: cou, minVal: 0})
            cact = cact+cou+",b:\$"+cou+"asdf},{a:"
            cou = cou + 1
          end; cact = cact[0..-5]+"]])"

          query.set("commitAction", cact).f(toLocale("finStackMobileExt::reorderSubmenu"), body)
        end else finHeaderForm(2, toLocale("finStackMobileExt::noSubMenu"))
      end else finHeaderForm(2, toLocale("finStackMobileExt::noMenuButtonSel"))
    end else finHeaderFuncs(stage, data)
  end
end


def ​

func:finHeaderFuncs ​

finHeaderFuncs(stage: null, data: null) ​

Backend functions for finHeaderForm function


meta ​

deffunc:finHeaderFuncs
deprecated✓
isfunc
liblib:finStackMobile
namefinHeaderFuncs
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(stage: null, data: null) => do
  r:(g)=> g.fromJSON
  if(readCount(finHeader) == 0) diff(null, {
    finHeader, buttons: "[{\"iconType\":\"icon\",\"icon\":\"icon-gear\","+
    "\"link\":\"finstack.eval('finHeaderForm()')\",\"linkType\":\"action\",\"label\":\"Edit Header\",\"open\":false}]"}, {add}).commit
  rec: read(finHeader)
  if(not rec.has("buttons") or (try not rec->buttons.r.isList catch true)) rec = rec.set("buttons", "[]")
  try stage = stage.toStr.parseInt catch stage = null

  if(stage == 0) do
    query: { "name": "finHeaderForm"+random(0..1000),"finForm": marker(),
      "cancelButton": "\$cancelButton","commitButton": "\$commitButton" }
    f:(g,h,i)=> g.set("dis",h).set("body",i.toJSON).toGrid.addMeta({formExecute: marker()})
    body: [
    {name: "hom1", editorType: "textinput", prompt: toLocale("finStackMobileExt::mobileHome"), defVal: if(rec.has("home")) rec->home.r[0] else "#"},
    {name: "hom2", editorType: "combobox", dataProvider: "[\"action\",\"hash\",\"url\"]", labelField: "val", selectedValueTags: "val",
      defIndex: if(rec.has("home")) ["action","hash","url"].index(rec->home.r[1]) else 1},
    {name: "sep", editorType: "separator"},
    {name: "disb", editorType: "checkbox", label: toLocale("finStackMobileExt::disableHeader"), defVal: if(rec.has("disable")) true else false},
    {name: "butn", editorType: "checkbox", label: toLocale("finStackMobileExt::editCreateMenus"), defVal: false},
    {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
    {name: "commitButton", editorType: "button", label: toLocale("finStackExt::next"), controlBar: true}]
    query.set("commitAction","finHeaderFuncs(1, [0, 0, [\$hom1, \$hom2], \$disb, \$butn])").f("Configure Header", body)
  end
  //////////////////////
  else if(stage == 1) do
    di: {}
    if(data[2][0].trim != "") di = di.set("home", data[2].toJSON)
    if(data[3]) do
      di = di.set("disable", marker())
      userReadAll(customHeaderDefault).toRecList.map(x=> x.diff({-customHeaderDefault, customHeaderDefaultDisabled})).commit
    end else do
      di = di.set("disable", removeMarker())
      userReadAll(customHeaderDefaultDisabled).toRecList.map(x=> x.diff({customHeaderDefault, -customHeaderDefaultDisabled})).commit
    end
    rec.diff(di).commit
    if(data[4]) finHeaderForm(2)
  end
  //////////////////////
  else if(stage == 3) do //add button
    rec = rec.diff({buttons: rec->buttons.r.add({label:toLocale("finStackMobileExt::bLineNew"),icon:"icon-plus",iconType:"icon",badgeValue:"",
      badgeClass:"",badgeQuery:"",link:"null",linkType:"action",children:null,open:false}).toJSON}).commit
    [rec, rec->buttons.r.size - 1]
  end
  //////////////////////
  else if(stage == 5) do //edit button
    btns: rec->buttons.r
    ind: data[1][0]
    data = data[1][1..-1]
    bn: btns[ind]

    if(data[6].trim != "") data = data.set(6, data[6].split(",").map(x=> x.toTagName).concat(","))

    if(data[5].startsWith("App:")) do
      prj: context()->projName
      if(data[5].endsWith("Builder")) do
        data = data.set(4,"/finMobile/"+prj+"#frame?url=/finLegacyProj/"+prj+"#builder")
      end
      else if(data[5].endsWith(toLocale("finStackMobileExt::rightMenuFolio"))) do
        data = data.set(4,"/finMobile/"+prj+"#frame?url=/finLegacyProj/"+prj+"#folio")
      end
      else if(data[5].endsWith(toLocale("finStackMobileExt::rightMenuFuncs"))) do
        data = data.set(4,"/finMobile/"+prj+"#frame?url=/finLegacyProj/"+prj+"#funcs:target="+ finCreateEmbeddedLink("funcUi2View") +"")
      end
      data = data.set(5,"url")
    end

    bn = bn.merge({label: data[0], badgeQuery: data[2], badgeClass: data[3], link: data[4], linkType: data[5], buttonTags: data[6]})
    if(data[1].size > 0) bn = bn.set("icon", data[1][0]->icon)
    btns = btns.set(ind, bn)

    rec.diff({buttons: btns.toJSON}).commit
    finHeaderForm(2, "Button Modified")
  end
  //////////////////////
  else if(stage == 4) do //remove button
    if(data[0] >= 0) do
      butns: rec->buttons.r.remove(data[0]).toJSON
      rec.diff({buttons: butns}).commit
      finHeaderForm(2, "Button removed")
    end
    else finHeaderForm(2, "No button selected")
  end
  //////////////////////
  else if(stage == 6) do //reorder buttons
    butns: []; a: rec->buttons.r
    data[1].each x=> butns = butns.add(a[x->a])
    rec.diff({buttons: butns.toJSON}).commit
    finHeaderForm(2, "Buttons Reordered")
  end
  //////////////////////
  else if(stage == 7) do //add submenu button
    btns: rec->buttons.r
    ind: data[0]
    if(not btns[ind].has("children") or not btns[ind]->children.isList) btns = btns.set(ind, btns[ind].set("children",[]))
    btns = btns.set(ind, btns[ind].set("children", btns[ind]->children.add({label:toLocale("finStackMobileExt::bLineNew"), icon:"icon-plus",
      iconType:"icon", badgeValue:"", badgeClass:"", badgeQuery:"", link:"null", linkType:"action"})))
    rec = rec.diff({buttons: btns.toJSON}).commit
    [rec, rec->buttons.r[ind]->children.size - 1, ind]
  end
  else if(stage == 9) do //edit submenu button
    btns: rec->buttons.r
    bind: data[1][0]
    sind: data[1][1]
    data = data[1][2..-1]
    bn: btns[bind]->children[sind]

    if(data[5].startsWith("App:")) do
      prj: context()->projName
      if(data[5].endsWith("Builder")) do
        data = data.set(4,"/finMobile/"+prj+"#frame?url=/finLegacyProj/"+prj+"#builder")
      end
      else if(data[5].endsWith(toLocale("finStackMobileExt::rightMenuFolio"))) do
        data = data.set(4,"/finMobile/"+prj+"#frame?url=/finLegacyProj/"+prj+"#folio")
      end
      else if(data[5].endsWith(toLocale("finStackMobileExt::rightMenuFuncs"))) do
        data = data.set(4,"/finMobile/"+prj+"#frame?url=/finLegacyProj/"+prj+"#funcs:target="+ finCreateEmbeddedLink("funcUi2View") +"")
      end
      data = data.set(5,"url")
    end

    bn = bn.merge({label: data[0], badgeQuery: data[2], badgeClass: data[3], link: data[4], linkType: data[5]})
    if(data[1].size > 0) bn = bn.set("icon", data[1][0]->icon)
    btns = btns.set(bind, btns[bind].set("children", btns[bind]->children.set(sind, bn)))

    rec.diff({buttons: btns.toJSON}).commit
    finHeaderForm(2, "Submenu Button Modified")
  end
  //////////////////////
  else if(stage == 8) do //remove submenu button
    if(data.size > 1 and not data[1].isList) do
      butns: rec->buttons.r
      subs: butns[data[0]]->children.remove(data[1])
      butns = butns.set(data[0], butns[data[0]].set("children", subs))
      rec.diff({buttons: butns.toJSON}).commit
      finHeaderForm(2, "Submenu button removed")
    end else finHeaderForm(2, "No submenu button selected")
  end
  ///////////////////////
  else if(stage == 10) do //reorder submenu buttons
    ind: data[1][0]; btn: []
    dat: data[1][1..-1].sort((x,y)=> x->b <=> y->b)
    a: rec->buttons.r
    dat.each x=> btn = btn.add(a[ind]->children[x->a])
    rec.diff({buttons: a.set(ind, a[ind].set("children",btn)).toJSON}).commit
    finHeaderForm(2, "Submenu Buttons Reordered")
  end
  ///////////////////////
  else if(stage == 11) do //return link type list
    ["action","hash","url",
    "App: DB Builder",
    "App: Folio",
    "App: Funcs"]
  end
end


def ​

func:finHeaderHomeForm ​

finHeaderHomeForm(data: null) ​

Axon function


meta ​

deffunc:finHeaderHomeForm
isfunc
liblib:finStackMobile
namefinHeaderHomeForm
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(data: null) => do
  home: try read(finHeader)->home.fromJSON catch ["#","hash"]

  if(data == null) do
    body: [
      {name: "hom1", editorType: "textinput", prompt: toLocale("finStackMobileExt::mobileHome"), defVal: home[0]},
      {name: "hom2", editorType: "combobox", dataProvider: "[\"action\",\"hash\",\"url\",\"Graphic\"]", labelField: "val", selectedValueTags: "val",
        defIndex: ["action","hash","url"].index(home[1])},

      {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
      {name: "commitButton", editorType: "button", label: toLocale("finStackExt::coreApply"), controlBar: true}
    ]

    {
      "dis": toLocale("finStackMobileExt::headerHomeButton"),
      "name": "finHeaderHomeForm",
      "body": body.toJSON,
      "cancelButton": "\$cancelButton",
      "commitButton": "\$commitButton",
      "commitAction": "finHeaderHomeForm([\$hom1, \$hom2])", //"read(finHeader).diff({home:[\$hom1, \$hom2].toJSON}).commit",
      "finForm": marker()
    }.toGrid.addMeta({formExecute: marker()})
  end
  else do
    if(data[1] != "Graphic") read(finHeader).diff({home: data.toJSON}).commit
    else do
      body: [
        {
          name:"grph",
          editorType:"combobox",
          prompt:toLocale("finStackMobileExt::chooseGraphic"),
          dataProvider:"readAll(fin5).sort((x,y)=> x.dis<=>y.dis)",
          labelField:"dis",
          selectedValueTags:"id",
          defIndex:0
        },

        {
          name:"targ",
          editorType:"list",
          prompt:toLocale("finStackMobileExt::chooseTarget"),
          labelField:"dis",
          selectedValueTags:"id",
          dataProvider:"readById(\$grph)->graphicOn.parseFilter.readAll.sort((x,y)=> x.dis<=>y.dis)",
          listType:"checkbox"
        },

        {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
        {name: "commitButton", editorType: "button", label: toLocale("finStackExt::coreApply"), controlBar: true}
      ]

      if(data.size > 2 and data[2] == true)
        body = body.insert(0,{name:"label",editorType:"label",text: toLocale("finStackMobileExt::pickTarget")})

      {"dis": toLocale("finStackMobileExt::headerHomeButtonGraphic"),
      "name": "finHeaderHomeForm"+random(0..10000),
      "body": body.toJSON,
      "cancelButton": "\$cancelButton",
      "commitButton": "\$commitButton",
      "commitAction": "if(size(\$targ)>0) finHeaderHomeForm([\"#frame?app=graphics&targetRef=@\"+(\$targ[0])+\"&url=%2Ffin5%2F"+context()->projName+"%3FprojectRef%3D%40\"+\$grph+\"%26title%3DshowSettings%23targetRef%3D%40\"+(\$targ[0]),\"hash\"]) else finHeaderHomeForm([0,0,true])",
      "finForm": marker()
      }.toGrid.addMeta({formExecute: marker()})
    end
  end
end


def ​

func:finHeaderMenu ​

finHeaderMenu(target: null) ​

Axon function


meta ​

deffunc:finHeaderMenu
isfunc
liblib:finStackMobile
namefinHeaderMenu
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(target:null) => do
  if(readCount(finHeader) == 0) diff(null, {finHeader, home:"[\"#\",\"hash\"]", buttons: "[{\"iconType\":\"icon\",\"icon\":\"icon-gear\","+
    "\"link\":\"app.NavigateToApp('settings');app.findAllComponents('settings')[0].get('finHeader')();\""+
    ",\"linkType\":\"action\",\"label\":\"Edit Header\",\"open\":false}]"}, {add}).commit
  header: read(finHeader)

  pointVars: g => [
    {
      label: toLocale("finStackExt::coreEdit"),
      icon: "icon-pencil",
      action: "finHeaderAddEditMenu(" + g + ")",
      keepOpen: true
    },
    {
      label: toLocale("finStackExt::remove"),
      icon: "icon-trash",
      style: "background-color: red",
      confirm: "Are you sure you want to remove?",
      action: "read(finHeader).diff({buttons:read(finHeader)->buttons.fromJSON.remove("+g+").toJSON}).commit",
      refresh: "finHeaderMenu()",
      keepOpen: true
    }
  ]

  list: [
    {
      displayName: toLocale("finStackMobileExt::editHeaderTitle"),
      isHeader: true,
      primaryHeader: true,
      isDivider: true,
      ignoreSettings,
      order: -9999
    }, {
      displayName: toLocale("finStackMobileExt::homeButton"),
      appId: "header",
      ignoreSettings: marker(),
      action: "finHeaderHomeForm()",
      finForm: true,
      icon: "icon-home",
      iconType: "class",
      keepOpen: true,
      ui: "html",
      minUiTarget: "phone",
      order: 1
    },
    {
      displayName: toLocale("finStackExt::back"),
      link: "",
      appId: "",
      icon: "icon-return",
      iconType: "class",
      keepOpen: true,
      action: "finSettingsMenuLegacy()",
      order: -1100,
      level: 0,
      ignoreSettings: marker(),
      folderPath: ""
    }
  ]

  if(header.has("disable")) list = list.add({
    displayName: toLocale("finStackMobileExt::enableHeader"),
    appId: "header",
    ignoreSettings: marker(),
    action: "read(finHeader).diff({-disable}).commit",
    refresh: "finHeaderMenu()",
    icon: "icon-checkmark",
    iconType: "class",
    keepOpen:true,
    ui: "html",
    minUiTarget: "phone",
    order: 2
  })
  else list = list.add({
    displayName: toLocale("finStackMobileExt::disableHeader"),
    appId: "header",
    ignoreSettings: marker(),
    action: "read(finHeader).diff({disable}).commit",
    refresh: "finHeaderMenu()",
    icon: "icon-cross",
    iconType: "class",
    keepOpen:true,
    ui: "html",
    minUiTarget: "phone",
    order: 2
  })

  list = list.addAll([
    {
      displayName: toLocale("finStackMobileExt::addButton"),
      appId: "header",
      ignoreSettings: marker(),
      action: "finHeaderAddEditMenu()",
      icon: "icon-plus",
      iconType: "class",
      keepOpen:true,
      ui: "html",
      minUiTarget: "phone",
      order: 3
    }
  ])

  if(header.has("buttons") and header->buttons.fromJSON.size > 0) do
    list = list.addAll([{
      displayName: toLocale("finStackMobileExt::reorderButtons"),
      appId: "header",
      ignoreSettings: marker(),
      action: "finHeaderReorderMenu()",
      icon: "icon-list",
      iconType: "class",
      keepOpen:true,
      ui: "html",
      minUiTarget: "phone",
      order: 4
    },{
      displayName: toLocale("finStackMobileExt::buttons"),
      isDivider: true,
      ignoreSettings,
      order: 5,
      secondaryHeader: true
    }])
    order: 0
    header->buttons.fromJSON.each x => do
      list = list.add({
        displayName: x->label,
        appId: "header",
        ignoreSettings: marker(),
        action: "null",
        icon: x->icon,
        iconType: "class",
        keepOpen: true,
        ui: "html",
        minUiTarget: "phone",
        order: order + 6,
        submenu: pointVars(order)
      })
      order = order + 1
    end
  end

  list.toGrid
end


def ​

func:finHeaderReorderFunc ​

finHeaderReorderFunc(idnex, child: null, dir) ​

Axon function


meta ​

deffunc:finHeaderReorderFunc
isfunc
liblib:finStackMobile
namefinHeaderReorderFunc
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(idnex, child: null, dir) => do
  if(child == null) do
    butns: read(finHeader)->buttons.fromJSON.map((x,y)=> x.set("order",y))

    if(idnex == 0 and dir or idnex == butns.size - 1 and not dir) 0 //pass
    else do
      if(dir) butns = butns.set(idnex, butns[idnex].set("order", butns[idnex]->order - 1.5))
      else butns = butns.set(idnex, butns[idnex].set("order", butns[idnex]->order + 1.5))
    end

    butns = butns.sort((x,y)=> x->order <=> y->order).map(x=> x.remove("order"))
    read(finHeader).diff({buttons: butns.toJSON}).commit
  end else do
    mainbutn: read(finHeader)->buttons.fromJSON[idnex]
    butns: mainbutn->children.map((x,y)=> x.set("order",y))

    if(idnex == 0 and dir or idnex == butns.size - 1 and not dir) 0 //pass
    else do
      if(dir) butns = butns.set(child, butns[child].set("order", butns[child]->order - 1.5))
      else butns = butns.set(child, butns[child].set("order", butns[child]->order + 1.5))
    end

    butns = butns.sort((x,y)=> x->order <=> y->order).map(x=> x.remove("order"))
    mainbutn = mainbutn.set("children", butns)

    read(finHeader).diff({buttons: read(finHeader)->buttons.fromJSON.set(idnex,mainbutn).toJSON}).commit
  end
end


def ​

func:finHeaderReorderMenu ​

finHeaderReorderMenu() ​

Axon function


meta ​

deffunc:finHeaderReorderMenu
isfunc
liblib:finStackMobile
namefinHeaderReorderMenu
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

() => do
  header: read(finHeader)

  refreshsettings: {
    funcCall: "finHeaderReorderMenu()",
    hideBackButton: true,
    display: "dis"
  }

  pointVars: g => [
    {
      label: toLocale("finStackMobileExt::up"),
      icon: "icon-arrow-up",
      action: "finHeaderReorderFunc("+g+",null,true)",
      refresh: "finHeaderReorderMenu()",
      keepOpen: true
    },
    {
      label: toLocale("finStackMobileExt::pointStatusDown"),
      icon: "icon-arrow-down",
      action: "finHeaderReorderFunc("+g+",null,false)",
      refresh: "finHeaderReorderMenu()",
      keepOpen: true
    }
  ]

  list: [
    {
      displayName: "— "+toLocale("finStackMobileExt::reorderButtons")+" —",
      primaryHeader: true,
      isDivider: true,
      ignoreSettings,
      order: -9999
    }
  ]

  order: 0
  header->buttons.fromJSON.each x=> do
    list = list.add({
      displayName: x->label,
      appId: "header",
      ignoreSettings: marker(),
      action: "null",
      icon: x->icon,
      iconType: "class",
      keepOpen:true,
      ui: "html",
      minUiTarget: "phone",
      order: order,
      submenu: pointVars(order)
    })
    order = order + 1
  end

  list.add({
      displayName: toLocale("finStackExt::back"),
      icon: "icon-return",
      iconType: "class",
      keepOpen: true,
      action: "finHeaderMenu()",
      order: -1100,
      level: 0,
      ignoreSettings: marker(),
  })
end


def ​

func:finHeaderReorderSubMenu ​

finHeaderReorderSubMenu(idnex) ​

Axon function


meta ​

deffunc:finHeaderReorderSubMenu
isfunc
liblib:finStackMobile
namefinHeaderReorderSubMenu
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(idnex) => do
  header: read(finHeader)

  pointVars: g => [
    {
      label: toLocale("finStackMobileExt::up"),
      icon: "icon-arrow-up",
      action: "finHeaderReorderFunc("+idnex+","+g+",true)",
      refresh: "finHeaderReorderSubMenu("+idnex+")",
      keepOpen: true
    },
    {
      label: toLocale("finStackMobileExt::pointStatusDown"),
      icon: "icon-arrow-down",
      action: "finHeaderReorderFunc("+idnex+","+g+",false)",
      refresh: "finHeaderReorderSubMenu("+idnex+")",
      keepOpen: true
    }
  ]

  list: [{
    displayName: "— "+toLocale("finStackMobileExt::reorderSubButtons")+" —",
    primaryHeader: true,
    isDivider: true,
    ignoreSettings,
    order: -9999
  }]

  order: 0
  header->buttons.fromJSON[idnex]->children.each x=> do
    list = list.add({
      displayName: x->label,
      appId: "header",
      ignoreSettings: marker(),
      icon: x->icon,
      iconType: "class",
      keepOpen:true,
      ui: "html",
      minUiTarget: "phone",
      order: order,
      submenu: pointVars(order)
    })
    order = order + 1
  end

  list.add({
    displayName: toLocale("finStackExt::back"),
    icon: "icon-return",
    iconType: "class",
    keepOpen: true,
    action: "finHeaderAddEditMenu("+idnex+")",
    order: -1100,
    level: 0,
    ignoreSettings: marker(),
  })
end


def ​

func:finHostChangePassForm ​

finHostChangePassForm(uname) ​

Axon function


meta ​

deffunc:finHostChangePassForm
isfunc
liblib:finStackMobile
namefinHostChangePassForm
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(uname) => do
  if(uname == "su") do
    body: [
    {name: "orig", editorType: "textinput", prompt: toLocale("finStackMobileExt::oldPassword"), defVal: "", password: true},
    {name: "new1", editorType: "textinput", prompt: toLocale("finStackMobileExt::newPassword"), defVal: "", password: true},
    {name: "new2", editorType: "textinput", prompt: toLocale("finStackMobileExt::confirmNew"), defVal: "", password: true},
    {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
    {name: "commitButton", editorType: "button", label: toLocale("finStackExt::coreApply"), controlBar: true}
    ]
  end
  else do
    body: [
    {name: "label", editorType: "label", text: toLocale("finStackMobileExt::passwordSigninPrompt")},
    {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::ok"), controlBar: true}
    ]
  end

  comAct:
  "if(trim(\$new1).size > 0) "+
    "if(\$new1==\$new2) try "+
      "finSetSuperUserPassword(\$orig,\$new1) "+
      "catch finFormAlertOk(\"Password Error\",\"Old Password Is Incorrect\") "+
    "else finFormAlertOk(\"Confirmation Error\",\"New Password Confirmation Mismatch\") "+
  "else finFormAlertOk(\"Password Error\",\"New Password Cannot Be Empty\")"

  {"dis": toLocale("finStackMobileExt::finPasswordChange"),
  "name": "finHostChangePassForm",
  "body": body.toJSON,
  "cancelButton": "\$cancelButton",
  "commitButton": "\$commitButton",
  "commitAction": comAct,
  "finForm": marker()
  }.toGrid.addMeta({formExecute: marker()})
end


def ​

func:finHostMainMenu ​

finHostMainMenu() ​

Axon function


meta ​

deffunc:finHostMainMenu
finStackMobileMenu✓
isfunc
liblib:finStackMobile
namefinHostMainMenu
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

() => do
  curUser: finGetCurrentUser()

  if(curUser->userRole == "su")
    [
      {
        displayName: toLocale("finStackMobileExt::rightMenuHost"),
        appId: "projectsApp",
        icon: "icon-to-do",
        iconType: "class",
        keepOpen: true,
        hasBadge: true,
        order: 206,
        badgeValue: projs().size,
        badgeTooltip: projs().size + " projects.",
        ui: "html",
        action: "window.open((finstack.pathPrefix || '')+'/home', '_blank')"
      }
    ]
  else []
end


def ​

func:finHostUpdateLicenseForm ​

finHostUpdateLicenseForm(uname, data: null) ​

Axon function


meta ​

deffunc:finHostUpdateLicenseForm
isfunc
liblib:finStackMobile
namefinHostUpdateLicenseForm
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(uname, data: null) => do
  if(not data.isRef) do
    body: [
    {name: "file", editorType: "file", prompt: toLocale("finStackMobileExt::hostUploadLicenseFile"), fileTypes: ["props"]},
    {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
    {name: "commitButton", editorType: "button", label: toLocale("finStackMobileExt::licenseUploadRestart"), controlBar: true}
    ]

    asdf: {"dis": toLocale("finStackMobileExt::finUpdateLicense"),
    "name": "finHostUpdateLicenseForm",
    "body": body.toJSON,
    "cancelButton": "\$cancelButton",
    "commitButton": "\$commitButton",
    "commitAction": "finHostUpdateLicenseForm(0,\$file)",
    "finForm": marker()
    }.toGrid.addMeta({formExecute: marker()})

    if(uname == 0) finFormAlertOk(toLocale("finStackMobileExt::folio.lite.error"),toLocale("finStackExt::folioRestoreNoFile"))
    else if(uname != "su") finFormAlertOk(toLocale("finStackMobileExt::folio.lite.error"),toLocale("finStackMobileExt::loggedInPrompt"))
    else asdf
  end
  ///////
  else do
    try do
      finUpdateLicense(data)
      finFormAlertOk(toLocale("finStackMobileExt::folio.lite.success"),toLocale("finStackMobileExt::standbyRestartManuallyPrompt"))
    end
    catch finFormAlertOk(toLocale("finStackMobileExt::folio.lite.error"),toLocale("finStackMobileExt::licenseUpdateFailure"))
  end
end


def ​

func:finHostUsageForm ​

finHostUsageForm() ​

Axon function


meta ​

deffunc:finHostUsageForm
isfunc
liblib:finStackMobile
namefinHostUsageForm
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

() => do
  licStat: lics().finGridFilter(expires)[0]

  body: [
    {
      name:"gridData",
      editorType: "table",
      dataProvider: "lics().finGridFilter(recCount).addColMeta(\"metric\", {dis: \"Metric\"}).addColMeta(\"usage\", {dis: \"Usage\"})" +
                    ".addColMeta(\"weight\", {dis: \"Weight\"}).addColMeta(\"recCount\", {dis: \"Records\"}).reorderCols([\"metric\", \"weight\", \"recCount\", \"usage\"])" +
                    ".renameCol(\"recCount\", \"records\")",
      editable: false,
      height: 125,
    },

    {
      name:"percentLabel",
      editorType: "label",
      text: toLocale("finStackMobileExt::sumTotal") + ": " + licStat->usage + "/" + licStat->limit + " [ " + licStat->statusMsg.replace("usage", "").trim + " ]"
    },

    {
      name:"commitButton",
      editorType:"button",
      label:toLocale("finStackExt::okay"),
      controlBar:true
    }

  ]

  { "dis": toLocale("finStackMobileExt::finMobileLicenseUsage"),
    "name":"finHostUsageForm",
    "body":body.toJSON,
    "width": 450,
    "commitButton":"\$commitButton",
    "commitAction": "",
    "finForm": marker()
  }.toGrid.addMeta({formExecute: marker()})
end


def ​

func:finInfoMenu ​

finInfoMenu(isSiemens: "") ​

Axon function


meta ​

deffunc:finInfoMenu
finStackMobileMenu✓
isfunc
liblib:finStackMobile
namefinInfoMenu
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(isSiemens: "") => do
  versionNum: try finGetPods("finStackExt") catch null
  if(versionNum != null) versionNum = versionNum->version

  item: {
    displayName: toLocale("finStackMobileExt::rightMenuDebug"),
    appId: "infoApp",
    link: "",
    icon: "icon-information",
    iconType: "class",
    ui: "html",
    minUiTarget: "phone",
    order: 208,
    classes:"tablet-only-hidden mobile-hidden",
    hasBadge: if(versionNum != null) true else false,
    badgeValue:  if(versionNum != null) "v"+versionNum else "",
    keepOpen: true
  }

  if(isSiemens != "" and isSiemens != null)
    item = item.merge({action: "window.app.ObtainMenu(null, 'null', 'info', " + finInfoSettings("forMenu2", null, isSiemens).set("hideBackButton", true).toAxonCode + ")"})
  else
    item = item.merge({action: ["window.app.ObtainMenu(null, 'null', 'infoApp', " + finInfoSettings("forMenu2").toAxonCode + ")"].concat("\n")})

  [item].toGrid
end


def ​

func:finInjectableProgramResources ​

finInjectableProgramResources() ​

Axon function


meta ​

deffunc:finInjectableProgramResources
finRemoteResource✓
isfunc
liblib:finStackMobile
namefinInjectableProgramResources
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

() => do
  [
    {dis:toLocale("finStackMobileExt::invokeActionsProgram"), value:"*`fan://finStackMobileExt/libs/invokeActions.json`"},
    {dis:toLocale("finStackMobileExt::showAndHideMyFilterPrograms") ,value:"*`fan://finStackMobileExt/libs/showAndHideMyFilter.json`"},
    {dis:toLocale("finStackMobileExt::enumFanProgram") ,value:"*`fan://finStackMobileExt/libs/enumFan.json`"},
    {dis:toLocale("finStackMobileExt::buttonToggleProgram") ,value:"*`fan://finStackMobileExt/libs/buttonToggleProgram.json`"},
    {dis:toLocale("finStackMobileExt::boolShowHideProgram") ,value:"*`fan://finStackMobileExt/libs/boolShowHide.json`"},
    {dis:toLocale("finStackMobileExt::toggleHideShowProgram") ,value:"*`fan://finStackMobileExt/libs/toggleHideShow.json`"},
    {dis:toLocale("finStackMobileExt::showHideByEnumProgram") ,value:"*`fan://finStackMobileExt/libs/showHideByEnum.json`"},
    {dis:toLocale("finStackMobileExt::hideRightMenuProgram") ,value:"*`fan://finStackMobileExt/libs/hideRightMenu.json`"},
    {dis:toLocale("finStackMobileExt::pointBubblesProgram") ,value:"*`fan://finStackMobileExt/libs/pointBubbles.json`"}
  ]
end


def ​

func:finJobMenu ​

finJobMenu() ​

Axon function


meta ​

deffunc:finJobMenu
finStackMobileMenu✓
isfunc
liblib:finStackMobile
namefinJobMenu
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

() => do
  [{
    displayName: toLocale("finStackMobileExt::rightMenuJobs"),
    appId: "jobApp",
    link: "",
    icon: "icon-document",
    iconType: "class",
    ui: "html",
    minUiTarget: "phone",
    order: 204,
    action: ["window.app.ObtainMenu(null, 'null', 'job', " + finJobSettings("forMenu2").toAxonCode + ")"].concat("\n"),
    hasBadge: true,
    classes:"tablet-only-hidden mobile-hidden",
    badgeValue: jobAppConfig().size,
    keepOpen: true }].toGrid
end


def ​

func:finJobSettings ​

finJobSettings(stage, inp: null) ​

Axon function


meta ​

deffunc:finJobSettings
isfunc
liblib:finStackMobile
namefinJobSettings
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(stage, inp: null) => do
  if(stage == "forMenu2") {
    //header: toLocale("finStackMobileExt::rightMenuJobs"),
    funcCall: "finJobMenu2()",
    display: "dis",
    hideBackButton: true
    }

  else if(stage == "forMenu3") {
    header: readById(inp)->dis.replace("\$","").replace("\"","").replace("\\",""),
    funcCall: "finJobMenu3(@"+inp+")",
    display: "dis",
    hideBackButton: true }

  else if(stage == "refresh") {
    displayName: toLocale("finStackExt::coreRefresh"),
    appId: "job",
    ignoreSettings: marker(),
    action: "window.app.ObtainMenu(null, 'null','job', "+inp+")",
    icon: "icon-retweet",
    iconType: "class",
    keepOpen:true,
    order: -1009 }

  else if(stage == "jobLogMenu") {
    header: toLocale("finStackMobileExt::debugLog"),
    funcCall: "jobLogMenu()",
    display: "dis",
    hideBackButton: true }

  else if(stage == "empty") {
    displayName: "",
    appId: "job",
    ignoreSettings: marker(),
    action: "null",
    iconType: "class",
    keepOpen:true,
    ui: "html",
    minUiTarget: "phone" }

  else if(stage == "divider") {
    displayName: inp,
    isDivider: true,
    appId: "job",
    keepOpen: true,
    order: 0,
    ignoreSettings: marker() }
end


def ​

func:finManualAddEditBacnetCommit ​

finManualAddEditBacnetCommit(props, connType, connRef: null, folderPath: null) ​

Axon function


meta ​

deffunc:finManualAddEditBacnetCommit
isfunc
liblib:finStackMobile
namefinManualAddEditBacnetCommit
overridable✓
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(props, connType, connRef: null, folderPath: null) => do
  connUri: ""
  connDict: {bacnetConn, finDiscoveryEnabled, conn, connPingFreq: 59s}

  defaultFolderPath: ""
  folderId: null
  isEmptyFolder: false

  //construct uri or props->macAdd.isEmpty)
  if(props->disName.isEmpty or (connType == "ip" and props->ip.isEmpty ) or (connType == "mstp" and (props->baudRate.isEmpty or props->mstpAdd.isEmpty or props->comPort.isEmpty)) or props->deviceInstance.isEmpty)
    return finFormManualAddEditBacnet(connRef, props, connType, folderPath)
  else if(connType == "ip") do
    connUri = "bacnet://"+props->ip+"/"+props->deviceInstance[0]

    if(not props->netNum.isEmpty) connUri = connUri + "?dnet="+props->netNum[0]
    if(not props->macAdd.isEmpty) connUri = connUri + (if(not props->netNum.isEmpty) "&" else "?") + "dadr="+props->macAdd[0].toHex

    connDict = connDict.merge({uri: connUri.parseUri, dis: props->disName})
  end else if(connType == "mstp") do
    connUri = "bacnetmstp://"+props->comPort+":"+props->mstpAdd[0]+"/"+props->deviceInstance[0]+"?"

    if(not props->netNum.isEmpty) connUri = connUri + "dnet="+props->netNum[0]

    connUri = connUri + (if(not props->netNum.isEmpty) "&" else "") + "baud="+props->baudRate[0]

    connDict = connDict.merge({path: props->comPort, uri: connUri.parseUri, dis: props->disName})
  end

  if(folderPath != null)
  do
    if(folderPath.startsWith("@"))
    do
      folderId = folderPath
      folderRec: readById(parseRef(folderId[1..-1]))
      isEmptyFolder = true

      if(folderRec.has("folderPath"))
        defaultFolderPath = folderRec->folderPath + "/" + folderRec->dis
      else
        defaultFolderPath = folderRec->dis
    end
    else
      defaultFolderPath = folderPath
  end

  if(defaultFolderPath != "") do
    defaultFolderPath = cleanFolderPathName(defaultFolderPath)
    connDict = connDict.merge({folderPath: defaultFolderPath})
  end

  if(connRef == null) diff(null, connDict, {add}).commit
  else readById(connRef).diff(connDict).commit

  if(isEmptyFolder)
    folderPathDelete(parseRef(folderId[1..-1]))
end


def ​

func:finMobileHardDelete ​

finMobileHardDelete(ids) ​

Axon function


meta ​

baSuExec✓
deffunc:finMobileHardDelete
isfunc
liblib:finStackMobile
namefinMobileHardDelete
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(ids) => do
  deleteRec: (idList) => do
    readByIds(idList).finHardDelete
  end

  if(not ids.isList()) ids = [ids]

  extList: readAll(ext).colToList("ext")
  useBaSu: extList.contains("ba") and extList.contains("systemOne")

  if(useBaSu) baSuExec(deleteRec, curFunc(), [ids])
  else deleteRec(ids)
end


def ​

func:finNavListChildren ​

finNavListChildren(query, folderPath, returnCount, addPoints) ​

Axon function


meta ​

deffunc:finNavListChildren
isfunc
liblib:finStackMobile
namefinNavListChildren

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function


def ​

func:finNavTreeDropOverrides ​

finNavTreeDropOverrides() ​

Axon function


meta ​

deffunc:finNavTreeDropOverrides
isfunc
liblib:finStackMobile
namefinNavTreeDropOverrides
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function


def ​

func:finNavTreeTypes ​

finNavTreeTypes(forDbTrees, searchDict) ​

Axon function


meta ​

deffunc:finNavTreeTypes
isfunc
liblib:finStackMobile
namefinNavTreeTypes
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function


def ​

func:finOMAddForm ​

finOMAddForm(stage: null, data: null, target: null) ​

Axon function


meta ​

deffunc:finOMAddForm
isfunc
liblib:finStackMobile
namefinOMAddForm
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(stage: null, data: null, target: null) => do
  if(stage == null or stage.isRef) do
    if(stage.isRef) do
      edit: true
      stage = stage.readById
    end
    else edit:false

    settings: {
      header: toLocale("finStackExt::rightMenuOMTitle"),
      funcCall: "finOMMenu2("+target.toAxonCode+")",
      hideBackButton: true,
      display: "dis"
    }.toAxonCode

    tmp: omManualsCategories()

    ctypeind: 0
    fpath: ""
    efileind: 0

    if(data==null) do
      if(edit) do
        disv: stage->dis
        conv: stage->contentOn
        linkv: stage->hyperlink
        ctypeind = tmp.toGrid.colToList("name").index(stage->contentType)
        if(stage.has("folderPath")) fpath = stage->folderPath
        if(stage->fileId != @null) efileind = readAll(file).sort((x,y)=> x->dis.lower <=> y->dis.lower).colToList("id").index(stage->fileId)
      end else do
        disv: ""
        if(target == null) conv: "id"
        else conv: readById(target).findAll((y,x)=> readById(target).trap(x) == marker()).names.concat(" and ")
        linkv: ""
      end
    end
    else do
      disv: data->dis
      conv: data->cOn
      linkv: data->link
    end

    body: [
    {name: "dis", editorType: "textinput", prompt: toLocale("finStackMobileExt::omMenuRescName"), defVal: disv},
    {name: "cOn", editorType: "filter", prompt: toLocale("finStackMobileExt::omMenuContentFilt"), defVal: conv},
    {name: "cType", editorType: "combobox", prompt: toLocale("finStackMobileExt::omMenuContentType"), dataProvider: tmp.toAxonCode, labelField: "dis", selectedValueTags: "name", defIndex: ctypeind},
    {name: "fPath", editorType: "textinput", prompt: toLocale("finStackMobileExt::omMenuFolderPath"), defVal: fpath},
    {name: "file", editorType: "file", prompt: toLocale("finStackMobileExt::omMenuUploadFile"), fileTypes:["pdf"]},
    {name: "link", editorType: "textinput", prompt: toLocale("finStackMobileExt::omMenuAddHyper"), defVal: linkv},
    {name: "efil", editorType: "combobox", prompt: toLocale("finStackExt::omMenuUseExisting"), labelField: "dis", defIndex: efileind,
      dataProvider: "readAll(file).sort((x,y)=> x->dis.lower <=> y->dis.lower)", selectedValueTags: "id"},
    {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
    {name: "commitButton", editorType: "button", label: toLocale("finStackExt::weatherMenuAdd"), controlBar: true}
    ]

    if(data != null) body = body.insert(0, {name: "label", editorType: "label", label: toLocale("finStackMobileExt::fillInAllFields")})

    comAct: "finOMAddForm(1, {dis: \$dis, cOn: \$cOn, cType: \$cType, fPath: \$fPath, file: [\$file], link: \$link, efil: \$efil}"
    if(edit) comAct = comAct + ", @"+stage->id
    comAct = comAct + ")"

    {"dis":(if(edit) toLocale("finStackExt::coreEdit") else toLocale("finStackExt::weatherMenuAdd")) + " " + toLocale("finStackMobileExt::omMenuOMResc"),
    "name":"finOMAddForm"+random(0..999),
    "body":body.toJSON,
    "cancelButton": "\$cancelButton",
    "commitButton": "\$commitButton",
    "commitAction": comAct,
    "completeAction": "setTimeout(function(){ window.app.ObtainMenu(null, 'null', 'folio'," + settings +"); }, 1000)",
    "finForm": marker()
    }.toGrid.addMeta({formExecute: marker()})
  end
  //////////////////////
  else if(stage == 1) do
    if(data->dis.trim!="" and data->cOn.trim!="" and (data->link.trim!="" or size(data->file)!=0)) do
      orec: null
      rec: {}
      params: {add}
      if(target.isRef) do
        orec = readById(target)
        params = {}
      end
      if(data->fPath.trim != "") rec = {folderPath: data->fPath}
      if(data->file.size > 0 and data->file[0].isRef) do
        tmp: readById(data->file[0])
        diff(orec, rec.merge({name: tmp->dis.toTagName, dis: data->dis, contentOn: data->cOn,
          fileId: tmp->id, hyperlink: data->link.parseUri, contentType: data->cType}),params).commit
      end else if(data->link.trim != "") do
        diff(orec,rec.merge({name: data->dis.toTagName, dis: data->dis, contentOn: data->cOn,
          fileId: @null, hyperlink: data->link.parseUri, contentType: data->cType}),params).commit
      end else do
        diff(orec,rec.merge({name: data->dis.toTagName, dis: data->dis, contentOn: data->cOn,
          fileId: data->efil, hyperlink: data->link.parseUri, contentType: data->cType}),params).commit
      end
    end
    else finOMAddForm(null, data)
  end
end


def ​

func:finOMContentOnForm ​

finOMContentOnForm(id, act, stage: null) ​

Axon function


meta ​

deffunc:finOMContentOnForm
isfunc
liblib:finStackMobile
namefinOMContentOnForm
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(id, act, stage: null) => do
  if(stage == null) do
    con: try readById(id)->contentOn catch ""

    body: [
    {name: "con", editorType: "textinput", prompt: toLocale("finStackMobileExt::contentOnPrompt"), defVal: con},
    {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
    {name: "commitButton", editorType: "button", label: toLocale("finStackExt::builderUpdate"), controlBar: true}
    ]

    {"dis": toLocale("finStackMobileExt::contentOnPrompt"),
    "name": "finOMContentOnForm",
    "body": body.toJSON,
    "cancelButton": "\$cancelButton",
    "commitButton": "\$commitButton",
    "commitAction": "finOMContentOnForm(@"+id+",\$con,1)",
    "completeAction": "window.app.ObtainMenu(null, 'null', 'omman',"+ act.toAxonCode +")",
    "finForm": marker()
    }.toGrid.addMeta({formExecute: marker()})
  end
  else if(stage == 1) do
    readById(id).diff({contentOn: act}).commit
  end
end


def ​

func:finOMDeleteForm ​

finOMDeleteForm(id, act) ​

Axon function


meta ​

deffunc:finOMDeleteForm
isfunc
liblib:finStackMobile
namefinOMDeleteForm
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(id, act) => do
  body: [
  {name: "label", editorType: "label", text: toLocale("finStackExt::folioFilesDeleteMsg").replace("{0}",toRec(id).dis)},
  {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::no"), controlBar: true},
  {name: "commitButton", editorType: "button", label: toLocale("finStackExt::yes"), controlBar: true}
  ]

  {"dis": toLocale("finStackMobileExt::folioQueryConfirm"),
  "name": "finOMDeleteForm",
  "body": body.toJSON,
  "cancelButton": "\$cancelButton",
  "commitButton": "\$commitButton",
  "commitAction": "toRec(@"+id+").finSoftDelete",
  "completeAction": "window.app.ObtainMenu(null, 'null', 'omman',"+ act.toAxonCode +")",
  "finForm": marker()
  }.toGrid.addMeta({formExecute: marker()})
end


def ​

func:finOMMenu ​

finOMMenu(target: null) ​

Axon function


meta ​

deffunc:finOMMenu
finStackMobileMenu✓
isfunc
liblib:finStackMobile
namefinOMMenu
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(target: null) => do
  settings: {
    //header: toLocale("finStackExt::rightMenuOMTitle"),
    funcCall: "finOMMenu2({{targetRef}})",
    hideBackButton: true,
    display: "dis" }

  [{
    displayName: toLocale("finStackExt::rightMenuOMTitle"),
    appId: "ommanApp",
    link: "",
    icon: "icon-archive",
    iconType: "class",
    ui: "html",
    minUiTarget: "phone",
    order: 6,
    action:  "window.app.ObtainMenu(null, 'null', 'ommanApp'," + settings.toAxonCode +")",
    hasBadge: true,
    classes:"tablet-only-hidden mobile-hidden",
    badgeValue: finContentOnFunc(target).size,
    keepOpen: true }].toGrid
end


def ​

func:finOMMenu2 ​

finOMMenu2(target: null, all: null) ​

Axon function


meta ​

deffunc:finOMMenu2
isfunc
liblib:finStackMobile
namefinOMMenu2
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(target: null, all: null) => do
  settings: {
    header: toLocale("finStackExt::rightMenuOMTitle"),
    funcCall: "finOMMenu2({{targetRef}})",
    hideBackButton: true,
    display: "dis" }
  recs: finContentOnFunc(target)
  tac: q => q.toAxonCode
  lst: omManualsCategories()

  mainDivider:{
    displayName: if(target==null) toLocale("finStackExt::rightMenuOMTitle") else toLocale("finStackMobileExt::omMenuOM") +": "+readById(target).dis,
    order: -1000,
    isDivider:true,
    ignoreSettings,
    header
  }

  list: [
    {displayName:  toLocale("finStackMobileExt::OMHeader"), isHeader: true, isDivider: true, ignoreSettings, order: -9999},
    {
    displayName: toLocale("finStackExt::coreRefresh"),
    appId: "omman",
    ignoreSettings: marker(),
    action: "window.app.ObtainMenu(null, 'null', 'omman'," + settings.tac +")",
    icon: "icon-retweet",
    iconType: "class",
    keepOpen:true,
    order: -1009 },
    {
    displayName: toLocale("finStackMobileExt::omMenuAddNewTitle"),
    appId: "omman",
    ignoreSettings: marker(),
    action: "finstack.eval('finOMAddForm(null,null,"+target.tac+")')",
    icon: "icon-plus",
    iconType: "class",
    keepOpen:true,
    ui: "html",
    minUiTarget: "phone",
    order: -1008 },
    {
    displayName: toLocale("finStackMobileExt::coreOrganize"),
    appId: "omman",
    ignoreSettings: marker(),
    action: "finstack.eval('finOrganizeFolderpathForm(\"contentOn\")')",
    icon: "icon-folder-open",
    iconType: "class",
    keepOpen:true,
    ui: "html",
    minUiTarget: "phone",
    order: -1008 },
    {
    displayName: toLocale("finStackMobileExt::omMenuAllResc"),
    appId: "omman",
    ignoreSettings: marker(),
    action: "window.app.ObtainMenu(null, 'null', 'omman'," + settings.set("funcCall","finOMMenu3("+target.tac+", "+all.tac+", null)").tac +")",
    icon: "icon-archive",
    iconType: "class",
    keepOpen:true,
    hasBadge: true,
    badgeValue: recs.size,
    ui: "html",
    minUiTarget: "phone",
    order: 0 }
  ]

  if(target != null) list = list.add({
    displayName: toLocale("finStackMobileExt::coreViewAll"),
    appId: "omman",
    ignoreSettings: marker(),
    action: "window.app.ObtainMenu(null, 'null', 'omman'," + settings.set("funcCall","finOMMenu2(null, true)").tac +")",
    icon: "icon-archive",
    iconType: "class",
    keepOpen:true,
    hasBadge: true,
    badgeValue: finContentOnFunc().size,
    ui: "html",
    minUiTarget: "phone",
    order: -1009 })

  cou: 1
  lst.each x => do
    if(recs.toGrid.finGridFilter(contentType==x->name).size > 0) do
      list = list.add({
        displayName: x->dis,
        appId: "omman",
        ignoreSettings: marker(),
        action: "window.app.ObtainMenu(null, 'null', 'omman'," + settings.set("funcCall","finOMMenu3("+target.tac+", "+all.tac+", `"+x->name+"`)").tac +")",
        icon: "icon-archive",
        iconType: "class",
        keepOpen:true,
        hasBadge: true,
        badgeValue: recs.toGrid.finGridFilter(contentType==x->name).size,
        ui: "html",
        minUiTarget: "phone",
        order: cou })
      cou = cou + 1
    end
  end

  if(all == true) list.addAll(finStackMenuBackButton(toLocale("finStackExt::rightMenuOMTitle"), settings, "omman")).toGrid
  else list.add(mainDivider).toGrid
end


def ​

func:finOMMenu3 ​

finOMMenu3(target: null, all: null, type: null) ​

Axon function


meta ​

deffunc:finOMMenu3
isfunc
liblib:finStackMobile
namefinOMMenu3
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(target: null, all: null, type: null) => do
  type = type.toStr
  if(type == "null") type = null
  tac: q=> q.toAxonCode
  settings: {
    header: toLocale("finStackExt::rightMenuOMTitle"),
    funcCall: "finOMMenu2("+target.tac+", "+all.tac+")",
    hideBackButton: true,
    display: "dis" }
  pName: context()->projName

  list: [{displayName: toLocale("finStackMobileExt::OMHeader"), isHeader: true, isDivider: true, ignoreSettings, order: -9999},]

  tagOpts: (g)=>{
    items: [{
      label: if(g->hyperlink.toStr.trim.size > 0) toLocale("finStackMobileExt::coreHyperlink") else toLocale("finStackExt::view"),
      icon: if(g->hyperlink.toStr.trim.size > 0) "icon-web" else "icon-preview",
      action: "window.open((finstack.pathPrefix || '')+'"+
        (if(g->hyperlink.toStr.trim.size > 0) g->hyperlink
        else if(g->fileId.readById->file.toStr.contains("pdf")) "/pod/finStackMobileExt/assets/pdf/pdfview.html#?proj="+pName+"&pdf=@"+g->fileId+"&page=1&scale=1"
        else "/finGetFile/"+pName+"?fileRef=@"+g->fileId)
        +"');",
      keepOpen: true },
      /*{
      label: toLocale("finStackMobileExt::reportsExport"),
      icon: "icon-mail",
      action: "finstack.eval('finFormAlertOk(\"Coming Soon\",\"The Email Feature Has Not Yet Been Implemented\")')",
      keepOpen: true },
      {
      label: "contentOn",
      icon: "icon-tag",
      action: "finstack.eval('finOMContentOnForm(@"+ g->id +", "+ settings.set("funcCall","finOMMenu3("+target.tac+", "+all.tac+", `"+type+"`)").tac +")')",
      keepOpen: true },*/
      {
      label: toLocale("finStackExt::coreEdit"),
      icon: "icon-pencil",
      action: "finstack.eval('finOMAddForm(@"+g->id+",null,"+target.toAxonCode+")')",
      keepOpen: true },
      {
      label: toLocale("finStackExt::delete"),
      icon: "icon-trash",
      action: "finstack.eval('finOMDeleteForm(@"+ g->id +", "+ settings.set("funcCall","finOMMenu3("+target.tac+", "+all.tac+", `"+type+"`)").tac +")')",
      style: "background-color: red",
      keepOpen: true }
    ]}.toJSON()

  tmp: {}
  recs: finContentOnFunc(target)
  if(type != null) recs = recs.toGrid.finGridFilter(contentType==type)
  recs.each x=> do
    tmp = {
      displayName: x->dis,
      appId: "omman",
      ignoreSettings: marker(),
      action: "null",
      icon: "icon-article",
      iconType: "class",
      keepOpen:true,
      ui: "html",
      submenu: tagOpts(x),
      minUiTarget: "phone",
      order: 0 }
    if(x.has("folderPath")) tmp = tmp.set("folderPath", x->folderPath)
    list = list.add(tmp)
  end

  list.addAll(finStackMenuBackButton(toLocale("finStackMobileExt::omMenuOM")+": "+(if(type==null) toLocale("finStackMobileExt::omMenuAll") else omManualsCategories(type).dis), settings, "omman")).toGrid
end


def ​

func:finProjectAuditForm ​

finProjectAuditForm(data: null) ​

Axon function


meta ​

deffunc:finProjectAuditForm
isfunc
liblib:finStackMobile
namefinProjectAuditForm
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(data: null) => do
  if(data == null) do
    body: [
      {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
      {name: "commitButton", editorType: "button", label: toLocale("finStackExt::coreApply"), controlBar: true}
    ]

    try am: read(projMeta)
    catch am: {}

    stat: false
    comAct: "finProjectAuditForm({"
    auditTags: [
      {tag: "auditAction", doc: toLocale("finStackMobileExt::logEachAction") },
      {tag: "auditCommit", doc: toLocale("finStackMobileExt::logEachCommit") }
    ]

    //tags(auditTag)
    auditTags.each x=> do
      stat = am.has(x->tag)
      body = body.add({name: x->tag, editorType: "checkbox", label: x->tag[5..-1]+" : "+x->doc, defVal: stat})
      comAct = comAct + x->tag + ": \$" + x->tag + ", "
    end

    comAct = comAct[0..-3] + "})"

    {
      "dis": toLocale("finStackMobileExt::auditSettings"),
      "name": "finProjectAuditForm",
      "body": body.toJSON,
      "cancelButton": "\$cancelButton",
      "commitButton": "\$commitButton",
      "commitAction": comAct,
      "finForm": marker()
    }.toGrid.addMeta({formExecute: marker()})
  end
  else do
    am: {} //{auditMeta: marker()}
    data.each((x,y)=> do
      if(x) am = am.set(y, marker())
      else am = am.set(y, removeMarker())
    end)
      read(projMeta).diff(am).commit //update old
  end
end


def ​

func:finProjectCategoryForm ​

finProjectCategoryForm(data: null, err: null) ​

Axon function


meta ​

deffunc:finProjectCategoryForm
isfunc
liblib:finStackMobile
namefinProjectCategoryForm
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(data: null, err: null) => do
  if(data == null) do
    body: [
      {
        name: "opt",
        editorType: "combobox",
        prompt: toLocale("finStackMobileExt::selectCategory"),
        labelField: "dis",
        selectedValueTags: "name",
        defIndex: 1,
        dataProvider: "{dis: toLocale(\"finStackExt::coreCreateNew\"), name: \"new\"}.toGrid.addRows(readAll(finCategory).sort(\"dis\").map(x=> if(x->dis.trim == \"\") x.merge({dis:x->name}) else x))"
      },

      { name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true },
      { name: "commitButton", editorType: "button", label: toLocale("finStackExt::next"), controlBar: true}
    ]

    {"dis": toLocale("finStackMobileExt::projCategories"),
    "name": "finProjectCategoryForm",
    "body": body.toJSON,
    "cancelButton": "\$cancelButton",
    "commitButton": "\$commitButton",
    "commitAction": "finProjectCategoryForm(\$opt)",
    "finForm": marker()
    }.toGrid.addMeta({formExecute: marker()})
  end
  //////////////////////
  else if(data.isStr)
  do
    try
      rec: read(finCategory and name==data)
    catch
      rec: {dis: toLocale("finStackMobileExt::bLineNew")}

    title: rec->dis+" Category"

    body: [
      {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
      {name: "commitButton", editorType: "button", label: toLocale("finStackExt::coreApply"), controlBar: true}
    ]

    if(data == "new")
    do
      if(err != null)
      do
        if (err->err == "duplicate")
          body = body.add({name: "label", editorType: "label", text: toLocale("finStackMobileExt::projCatNameExists")})
        else if (err->err == "invalidName")
          body = body.add({name: "label", editorType: "label", text: toLocale("finStackMobileExt::enterValidName")})
      end

      body = body.addAll([
        {name: "one", editorType: "textinput", prompt: toLocale("finStackMobileExt::reportColName"), defVal: if (err != null) err->name.replace("_finCat", "") else ""},
        {name: "two", editorType: "textinput", prompt: toLocale("finStackMobileExt::hostDisplayName"), defVal: if (err != null) err->dis else ""}
      ])

      comAct: "\$one, \$two, null"
    end
    else if(data == "hvac_finCat") do
      body = body.addAll([
      {name: "one", editorType: "label", prompt: toLocale("finStackMobileExt::reportColName"), text: rec->name[0..-8]},
      {name: "two", editorType: "textinput", prompt: toLocale("finStackMobileExt::hostDisplayName"), defVal: rec->dis}
      ])
      comAct: "null, \$two, null"
    end
    else do
      body = body.addAll([
      {name: "one", editorType: "label", prompt: toLocale("finStackMobileExt::reportColName"), text: rec->name[0..-8]},
      {name: "two", editorType: "textinput", prompt: toLocale("finStackMobileExt::hostDisplayName"), defVal: rec->dis},
      {name: "three", editorType: "checkbox", label: toLocale("finStackExt::delete"), defVal: false}
      ])
      comAct: "\$one, \$two, \$three"
    end

    {"dis": title,
    "name": "finProjectCategoryForm"+random(0..10000),
    "body": body.toJSON,
    "cancelButton": "\$cancelButton",
    "commitButton": "\$commitButton",
    "commitAction": "finProjectCategoryForm(["+data.toAxonCode+","+comAct+"])",
    "finForm": marker()
    }.toGrid.addMeta({formExecute: marker()})
  end
  //////////////////////
  else do
    name: data[0]
    if(name == "new")
    do
      dataAsDict: {dis: data[2], finCategory, name: data[1]+"_finCat"}

      try
      do
        if(readCount(finCategory and name==data[1]+"_finCat") == 0)
          diff(null, dataAsDict, {add}).commit
        else
          finProjectCategoryForm("new", dataAsDict.merge({err: "duplicate", -finCategory}))
      end
      catch (err)
      do
        if( err->dis.contains("InvalidTagValErr"))
          finProjectCategoryForm("new", dataAsDict.merge({err: "invalidName", -finCategory}))
        else
          finFormAlertOk(toLocale("finStackExt::regError"), toLocale("finStackMobileExt::newProjCatFailed"))
      end
    end
    else do
      if(data[3] == true) read(finCategory and name==name).finHardDelete
      else do
        asdf: {}
        if(data[1] != null) asdf = asdf.set("name", data[1]+"_finCat")
        if(data[2] != null) asdf = asdf.set("dis", data[2])
        read(finCategory and name==name).diff(asdf).commit
      end
    end
  end
end


def ​

func:finProjectEmailForm ​

finProjectEmailForm(data: null) ​

Axon function


meta ​

deffunc:finProjectEmailForm
isfunc
liblib:finStackMobile
namefinProjectEmailForm
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(data: null) => do
  if(data == null) do
    rec: {}
    hs: hostSettings("email", {password}) //fill in with default data
    hs.each x=> rec = rec.set(x->name, if(x.has("defVal")) x->defVal else "")
    try do //fill in with user defined data
      ["tls", "from", "uri", "username"].each x=> do
        if(hs.meta->rec[x] != null) rec = rec.set(x, hs.meta->rec[x])
      end
    end catch 0

    body: [
      {name: "host", editorType: "textinput", prompt: toLocale("finStackMobileExt::rightMenuHost"), defVal: rec->uri.toStr},
      {name: "user", editorType: "textinput", prompt: toLocale("finStackExt::settingsMenuUsername"), defVal: rec->username},
      {name: "pass", editorType: "textinput", prompt: toLocale("finStackExt::settingsMenuPassword"), defVal: "**********", password: true},
      {name: "send", editorType: "textinput", prompt: toLocale("finStackMobileExt::settingsMenuFrom"), defVal: rec->from},
      {name: "ussl", editorType: "checkbox", label: toLocale("finStackMobileExt::settingsMenuSsl"), defVal: try rec->tls catch true},
      {name: "test", editorType: "checkbox", label: toLocale("finStackMobileExt::testSMTPConfig"), defVal: false},
      {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
      {name: "commitButton", editorType: "button", label: toLocale("finStackExt::coreApply"), controlBar: true}
    ]

    {
      "dis": toLocale("finStackMobileExt::emailSMTPSettings"),
      "name": "finProjectEmailForm",
      "body": body.toJSON,
      "cancelButton": "\$cancelButton",
      "commitButton": "\$commitButton",
      "commitAction": "finProjectEmailForm({host: \$host, username: \$user, password: \$pass, from: \$send, ssl: \$ussl, test: \$test})",
      "finForm": marker()
    }.toGrid.addMeta({formExecute: marker()})
  end
  ///////////////////////
  else if(data.isDict) do
    hc: {
      id: @h:email,
      mod: hostReadById(@h:email)->mod,
      tls: data["ssl"] == true,
      uri: data->host.parseUri,
      from: data->from,
      username: data->username,
      sysMod
    }
    if(data->password != "**********")
      hc = hc.set("password", {secret: data->password})

    hostCommit(hc)

    if(data->test) do
      body: [
        {name: "recv", editorType: "textinput", prompt: toLocale("finStackMobileExt::reportsEmailTo"), defVal: data->from},
        {name: "subj", editorType: "textinput", prompt: toLocale("finStackMobileExt::emailSubject"), defVal: "[TEST] FIN Stack - "+now().format("YYYY-MM-DD hh:mm AA")},
        {name: "mesg", editorType: "textarea", prompt: toLocale("finStackMobileExt::alarmGridHeaderMessage"), defVal: "FIN Stack Test Email : Just A Test"},
        {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
        {name: "commitButton", editorType: "button", label: toLocale("finStackMobileExt::settingsMenuTest"), controlBar: true}
      ]

      {
        "dis": toLocale("finStackMobileExt::testSMTPConfig"),
        "name": "finProjectEmailForm2",
        "body": body.toJSON,
        "cancelButton": "\$cancelButton",
        "commitButton": "\$commitButton",
        "commitAction": "finEmailSendTest(\$recv, \$subj, \$mesg).finProjectEmailForm",
        "finForm": marker()
      }.toGrid.addMeta({formExecute: marker()})
    end
  end
  //////////////////////
  else if(data.isStr) do
    body: [
      {name: "mesg", editorType: "textarea", defVal: data, editable: false, height: 350},
      {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::done"), controlBar: true},
    ]

    {"dis": toLocale("finStackMobileExt::testSMTPConfig"),
    "name": "finProjectEmailForm3",
    "body": body.toJSON,
    "cancelButton": "\$cancelButton",
    "finForm": marker()
    }.toGrid.addMeta({formExecute: marker()})
  end
end


def ​

func:finProjectProjectForm ​

finProjectProjectForm() ​

Axon function


meta ​

deffunc:finProjectProjectForm
isfunc
liblib:finStackMobile
namefinProjectProjectForm
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

() => do
  body: [
    {name: "name", editorType: "textinput", prompt: toLocale("finStackMobileExt::projDispName"), defVal: read(projMeta)->dis},
    {name: "desc", editorType: "textarea", prompt: toLocale("finStackMobileExt::projDescription"), defVal: read(projMeta)->doc, height: 150},
    {name: "cancelButton", editorType: "button", label: toLocale("finStackExt::cancel"), controlBar: true},
    {name: "commitButton", editorType: "button", label: toLocale("finStackExt::coreApply"), controlBar: true}
  ]

  {"dis": toLocale("finStackMobileExt::projSettings"),
  "name": "finProjectProjectForm",
  "body": body.toJSON,
  "cancelButton": "\$cancelButton",
  "commitButton": "\$commitButton",
  "commitAction": "read(projMeta).diff({dis: \$name, doc: \$desc}).commit",
  "finForm": marker()
  }.toGrid.addMeta({formExecute: marker()})
end


def ​

func:finQueries ​

finQueries() ​

Axon function


meta ​

deffunc:finQueries
finCommonQuery✓
isfunc
liblib:finStackMobile
namefinQueries
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

() => do
  queries: [
    {
      dis: toLocale("finStackMobileExt::folioTrashEmpty"),
      query: "folioEmptyTrash()",
      folderPath: toLocale("finStackExt::trash") + "/",
      toolTip: toLocale("finStackMobileExt::commonQueries.emptyTash.tooltip")
    },

    {
      dis: toLocale("finStackMobileExt::findGraphics"),
      query: "readAll(graphicOn)",
      folderPath: toLocale("finStackExt::rightMenuGraphicsTitle") + "/",
      toolTip: toLocale("finStackMobileExt::commonQueries.findGraphics.tooltip")
    },

    {
      dis:  toLocale("finStackMobileExt::readFinFile"),
      query: "readFinFile(@121321)",
      folderPath: toLocale("finStackMobileExt::rightMenuGraphicsBuilder") + "/",
      toolTip: toLocale("finStackMobileExt::commonQueries.readFinFile.tooltip")
    },

    {
      dis: toLocale("finStackMobileExt::readAllFiles"),
      query: "readAll(file)",
      folderPath: toLocale("finStackMobileExt::folioMenuFiles") + "/",
      toolTip: toLocale("finStackMobileExt::commonQueries.readAllFiles.tooltip")
    },

    {
      dis: toLocale("finStackMobileExt::thisWeeksKwAvg"),
      query: "readAll(point and power).hisRead(thisWeek).hisRollup(avg, 1day)",
      folderPath: toLocale("finStackMobileExt::alarmHistory") + "/",
      toolTip: toLocale("finStackMobileExt::commonQueries.thisWeeksKwAvg.tooltip")
    },

    {
      dis: toLocale("finStackMobileExt::thisYearsKwAvg"),
      query: "readAll(point and energy).hisRead(thisYear).hisRollup(avg, 1mo)",
      folderPath: toLocale("finStackMobileExt::alarmHistory") + "/",
      toolTip: toLocale("finStackMobileExt::commonQueries.thisYearsKwAvg.tooltip")
    },

    {
      dis: toLocale("finStackMobileExt::thisWeeksWarmestZone"),
      query: "readAll(zone and temp and sensor and point).hisRead(thisWeek).hisRollup(max, 1day)",
      folderPath: toLocale("finStackMobileExt::alarmHistory") + "/",
      toolTip: toLocale("finStackMobileExt::commonQueries.thisWeeksWarmestZone.tooltip")
    },

    {
      dis: toLocale("finStackMobileExt::pastYearKwAvg"),
      query: "readAll(point and power).hisRead(pastYear).hisRollup(avg, 3mo)",
      folderPath: toLocale("finStackMobileExt::alarmHistory") + "/",
      toolTip: toLocale("finStackMobileExt::commonQueries.pastYearKwAvg.tooltip")
    },

    {
      dis: toLocale("finStackMobileExt::autoAddAhuRefs"),
      query: "readAll(vav and not ahuRef).map(x=> x.diff({ahuRef:read(ahu and equip and vavZone and floorRef==x->floorRef)->id}).commit())",
      folderPath: toLocale("finStackMobileExt::dbOptimization") + "/",
      toolTip: toLocale("finStackMobileExt::commonQueries.autoAddAhuRefs.tooltip")
    },

    {
      dis: toLocale("finStackMobileExt::createDefTunPol"),
      query: "[diff(null, {dis:\"fastSensor\",pollTime:13s,connTuning},{add}), diff(null, {dis:\"mediumCmd\",pollTime:21s, connTuning},{add}), diff(null, {dis:\"slowSp\",pollTime:47s,connTuning},{add}), diff(null, {dis:\"bacnetDefault\",pollTime:61s,connTuning},{add})].commit",
      folderPath: toLocale("finStackExt::tunPolicies") + "/",
      toolTip: toLocale("finStackMobileExt::commonQueries.createDefTunPol.tooltip")
    },

    {
     dis: toLocale("finStackMobileExt::showAllTunPol"),
      query: "readAll(connTuning)",
      folderPath: toLocale("finStackExt::tunPolicies") + "/",
      toolTip: toLocale("finStackMobileExt::commonQueries.showAllTunPol.tooltip")
    },

    {
      dis: toLocale("finStackMobileExt::assignDefTunPol"),
      query: "[readAll(point and sp and not connTuningRef).toRecList.map(x=> x.diff({connTuningRef:read(connTuning and dis==\"slowSp\")->id})).commit, readAll(point and cmd and not connTuningRef).toRecList.map(x=> x.diff({connTuningRef:read(connTuning and dis==\"mediumCmd\")->id})).commit, readAll(point and sensor and not connTuningRef).toRecList.map(x=> x.diff({connTuningRef:read(connTuning and dis==\"fastSensor\")->id})).commit]",
      folderPath: toLocale("finStackExt::tunPolicies") + "/",
      toolTip: toLocale("finStackMobileExt::commonQueries.assignDefTunPol.tooltip")
    },

    {
      dis: toLocale("finStackMobileExt::tagVavsWithNavName"),
      query: "readAll(equip).findAll(x=> x->navName.lower.contains(\"vav\")).toRecList.map(x=> x.diff({vav}).commit())",
      folderPath: toLocale("finStackMobileExt::dbOptimization") + "/",
      toolTip: toLocale("finStackMobileExt::commonQueries.tagVavsWithNavName.tooltip")
    },
  ]

  if (finConnExts().find(v => v->name == "bacnet") != null)
    return queries.addAll([
      {
        dis: toLocale("finStackMobileExt::syncBacnetPointDis"),
        query: "readAll(point and not description and bacnetConnRef).map(x=> try x.diff({description:bacnetReadObjectProperty(x->bacnetConnRef, x->bacnetCur, \"description\")[0]->value}).commit() catch \"\")",
        folderPath: toLocale("bacnetExt::bacnet.ext.dis") + "/",
        toolTip: toLocale("finStackMobileExt::commonQueries.syncBacnetPointDis.tooltip")
      },

      {
        dis: toLocale("finStackMobileExt::addIpConnToBacnetConns"),
        query: "readAll(bacnetConn).map (x=> x.diff({ipAddr:x->uri.toStr.split(\"/\")[2]}).commit())",
        folderPath: toLocale("bacnetExt::bacnet.ext.dis") + "/" + toLocale("finStackMobileExt::miniDb.connectionDetails"),
        toolTip: toLocale("finStackMobileExt::commonQueries.addIpConnToBacnetConns.tooltip")
      },

      {
        dis: toLocale("finStackMobileExt::addNetNumToBacnetConns"),
        query: "readAll(bacnetConn).map(x=> try x.diff({networkNumber:x->uri.toStr.split(\"=\")[-2].split(\"&\")[0]}).commit() catch \"\")",
        folderPath: toLocale("bacnetExt::bacnet.ext.dis") + "/" + toLocale("finStackMobileExt::miniDb.connectionDetails"),
        toolTip: toLocale("finStackMobileExt::commonQueries.addNetNumToBacnetConns.tooltip")
      },

      {
        dis: toLocale("finStackMobileExt::addInstNumToBacnetConns"),
        query: "readAll(bacnetConn).map(x=> x.diff({instanceNumber:x->uri.toStr.split(\"?\")[0].split(\"/\")[-1]}).commit())",
        folderPath: toLocale("bacnetExt::bacnet.ext.dis") + "/" + toLocale("finStackMobileExt::miniDb.connectionDetails"),
        toolTip: toLocale("finStackMobileExt::commonQueries.addInstNumToBacnetConns.tooltip")
      },

      {
        dis: toLocale("finStackMobileExt::addMacAddToBacnetConns"),
        query: "readAll(bacnetConn).map(x=> try x.diff({hexMacAddr:x->uri.toStr.split(\"=\")[-1]}).commit() catch \"\")",
        folderPath: toLocale("bacnetExt::bacnet.ext.dis") + "/" + toLocale("finStackMobileExt::miniDb.connectionDetails"),
        toolTip: toLocale("finStackMobileExt::commonQueries.addMacAddToBacnetConns.tooltip")
      }
    ])

  else queries
end


def ​

func:finReadByIdTrash ​

finReadByIdTrash(id, checked) ​

Axon function


meta ​

deffunc:finReadByIdTrash
isfunc
liblib:finStackMobile
namefinReadByIdTrash

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function


def ​

func:finReadByIdsTrash ​

finReadByIdsTrash(ids, checked) ​

Axon function


meta ​

deffunc:finReadByIdsTrash
isfunc
liblib:finStackMobile
namefinReadByIdsTrash

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function


def ​

func:finReadCsvWithEmbeddedDelimeter ​

finReadCsvWithEmbeddedDelimeter(csvSource, delimeter) ​

Axon function


meta ​

deffunc:finReadCsvWithEmbeddedDelimeter
isfunc
liblib:finStackMobile
namefinReadCsvWithEmbeddedDelimeter

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function


def ​

func:finReadHeader ​

finReadHeader() ​

finReadHeader()

Returns content of finHeader record. Will return "null" if finHeader record has disable tag or if cannot parse finHeader data or if record does not exist. Adds a default home button for going to /finMobile/projName


meta ​

deffunc:finReadHeader
isfunc
liblib:finStackMobile
namefinReadHeader
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

() => do
  if(readCount(finHeader) > 0 and not read(finHeader).has("disable")) do
    stuff: read(finHeader)
    header: {}
    uname: context()->username
    headerFilter: ""

    if(uname != "su") do
      user: finGetCurrentUser() //userRead(username==uname)
      if(user.has("headerFilter")) headerFilter = user->headerFilter.trim
    end

    ln: "/finMobile/"+context()->projName
    lnt: "url"
    if(stuff.has("home")) do
      try do
      ln = stuff->home.fromJSON
      lnt = ln[1]
      ln = ln[0]
      end catch(e) logErr("finHeader", toLocale("finStackMobileExt::failedToReadHeader"), e)
    end

    buttons: []

    if(stuff.has("buttons")) try
      stuff->buttons.fromJSON.each x=> do
        try x = x.set("badgeValue", x->badgeQuery.eval.toStr) catch 0
        if(x.has("children") and x->children.isList) try x = x.set("children", x->children.map(y=> do
          try y.set("badgeValue", y->badgeQuery.eval.toStr) catch y
        end)) catch 0
        buttons = buttons.add(x)
      end
    catch(e) logErr("finHeader", toLocale("finStackMobileExt::failedToReadHeaderButtons"), e)

    if(headerFilter != "") do
      buttons = buttons.findAll(x=> do
        if(x.has("buttonTags") and x->buttonTags.trim != "") do
          tmp: {}
          x->buttonTags.split(",").each y=> tmp = tmp.set(y,marker())
          tmp.toGrid.finGridFilter(parseFilter(headerFilter)).size > 0
        end else false
      end)
    end

    buttons = buttons.insert(0,{
      label:toLocale("finStackMobileExt::mobileHome"),
      icon:"icon-home",
      iconType:"icon",
      badgeValue:"",
      badgeClass:"",
      link: ln,
      linkType: lnt,
      children: null,
      open: false})

    header.set("buttons", buttons).toJSON
  end else "null"
end

/*
if user no tags: show all buttons
elif button no tags: don't show
else: show buttons with same tags

user has filter, buttons have list of tags
*/

/*
  sampleData : {
    logoPath    : "http://1.bp.blogspot.com/-UW2-sSelVvA/TtyhiVhFn_I/AAAAAAAAAR8/BmoqvCE6l3U/s1600/Siemens_logo.png",
    title       : "Awesome App",
    buttons : [
       {
         label:"Play Time",
         icon:"icon-basketball",
         iconType:"icon",
         badgeValue:"12",
         badgeClass:"success",
         badgeQuery: "readCount(site)",
         link: "console.log('asdf')",
         linkType: "action",
         children: [{
           label:"Menu Action",
           icon:"icon-menu",
           iconType:"icon",
           badgeValue:"12",
           badgeClass:"success",
           badgeQuery: "readCount(site)",
           link: "http://google.com",
           linkType: "url",
         }, {
           label:"Sexy Time",
           icon:"icon-card",
           iconType:"icon",
           badgeValue:"67",
           badgeClass:"focus",
           badgeQuery: "readCount(site)",
           link: "frame?url=%2FfinLegacyProj%2Fdemo%23builder",
           linkType: "hash",
         }],
         open: false
      },
      {
         label:"Naintek",
         icon:"icon-cart",
         iconType:"icon",
         badgeValue:"",
         badgeClass:"",
         link: "console.log(1234)",
         linkType: "action",
         children: null,
         open: false
      }
    ]
  }.toJSON
[{"children":[{"iconType":"icon","icon":"icon-menu","link":"http://google.com","linkType":"url","label":"Menu Action","badgeValue":"12","badgeClass":"success","badgeQuery":"readCount(site)"},{"iconType":"icon","icon":"icon-card","link":"frame?url=%2FfinLegacyProj%2Fdemo%23builder","linkType":"hash","label":"Sexy Time","badgeValue":"67","badgeClass":"focus"}],"iconType":"icon","icon":"icon-basketball","link":"console.log('asdf')","linkType":"action","label":"Play Time","badgeValue":"12","badgeQuery":"readCount(site)","badgeClass":"success","open":false},{"iconType":"icon","icon":"icon-cart","link":"console.log(1234)","linkType":"action","label":"Naintek","badgeQuery":"readCount(equip)","badgeValue":"","badgeClass":"error","open":false}]
*/


def ​

func:finRestartFinstack ​

finRestartFinstack() ​

Axon function


meta ​

deffunc:finRestartFinstack
isfunc
liblib:finStackMobile
namefinRestartFinstack
su✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function


def ​

func:finRunSelectedTool ​

finRunSelectedTool(id, targets, tool) ​

Axon function


meta ​

deffunc:finRunSelectedTool
isfunc
liblib:finStackMobile
namefinRunSelectedTool
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

(id, targets, tool) => do
  params: ""
  tool = tool[0]

  if(targets.size == 0 or (targets.size == 1 and targets[0] == null)) targets = []
  else
  do
    try targets.toRecList
    catch
    do
      temp: targets

      if (temp[0].isRef)
        temp = readByIds(targets, false).findAll(v => v.has("id"))
      else
        temp = readByIds(targets.map(r => r->id), false).findAll(v => v.has("id"))

      if (temp.size == 0)
        targets = []
      else
        targets = temp
    end
  end

  if(tool->src.startsWith("(id")) do
    if(targets.size > 0) params = targets[0].toAxonCode
    else params = "null"

    if(tool->src.contains("selectedDicts"))
      params = params + ", " + targets.toRecList.toAxonCode
  end else if(tool->src.startsWith("(selectedDicts"))
    params = targets.toRecList.toAxonCode

  func:tool->name + "(" + params + ")"

  eval(func)
end


def ​

func:finSettingsMenu ​

finSettingsMenu() ​

Axon function


meta ​

deffunc:finSettingsMenu
finStackMobileMenu✓
isfunc
liblib:finStackMobile
namefinSettingsMenu
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

() => do
  [{
    displayName: toLocale("finStackMobileExt::rightMenuSettings"),
    link: "",
    appId: "settingsApp",
    icon: "icon-gear",
    iconType: "class",
    action: "app.LoadApplication('/pod/finSettings/index.html#page=settingsPage', undefined, undefined, {app: 'settings'});",
    level: 0,
    keepOpen: false,
    order: 203,
    ui: "html",
    classes:"tablet-only-hidden mobile-hidden",
    }].toGrid
end


def ​

func:finSettingsMenuLegacy ​

finSettingsMenuLegacy() ​

Axon function


meta ​

deffunc:finSettingsMenuLegacy
isfunc
liblib:finStackMobile
namefinSettingsMenuLegacy
private✓

supertypes ​

featureFeature namespace of definitions formatted as feature:name
funcAxon function

src ​

() => do
  settings: {
    funcCall: "finSettingsMenu1()",
    display: "dis",
    hideBackButton: true,
    paginateCount: 1000
  }
  settings2: {
    funcCall: "finProjectMenu()",
    hideBackButton: true,
    display: "dis"
  }
  settings3: {
    funcCall: "finHeaderMenu()",
    hideBackButton: true,
    display: "dis"
  }

  [
    {
      displayName: toLocale("finStackMobileExt::legacySettings"),
      primaryHeader: true,
      isDivider: true,
      ignoreSettings,
      order: -9999
    }, {
      displayName: toLocale("finStackMobileExt::extension"),
      appId: "settingsApp",
      ignoreSettings,
      // action: [/*"window.app.LoadApplication('"+finCreateEmbeddedLink("extSettings")+"')",*/ "window.app.ObtainMenu(null, 'null', 'settingsApp',"+ settings.toAxonCode +")"].concat("\n"),
      action: "finSettingsMenu1()",
      icon: "icon-gear",
      iconType: "class",
      keepOpen: true,
      ui: "html",
      minUiTarget: "phone",
      order: 1
    }, {
      displayName: toLocale("finStackMobileExt::project"),
      appId: "settingsApp",
      ignoreSettings,
      // action: [/*"window.app.LoadApplication('"+finCreateEmbeddedLink("projSettings")+"')",*/ "window.app.ObtainMenu(null, 'null', 'settingsApp',"+ settings2.toAxonCode +")"].concat("\n"),
      action: "finProjectMenu()",
      icon: "icon-toggles",
      iconType: "class",
      keepOpen: true,
      ui: "html",
      minUiTarget: "phone",
      order: 2
    }, {
      displayName: toLocale("finStackMobileExt::header"),
      appId: "settingsApp",
      ignoreSettings,
      // action: "window.app.ObtainMenu(null, 'null', 'settingsApp',"+ settings3.toAxonCode +")", //"finstack.eval('finHeaderForm()')",
      action: "finHeaderMenu()",
      icon: "icon-browser",
      iconType: "class",
      keepOpen: true,
      ui: "html",
      minUiTarget: "phone",
      order: 3
    }, {
      displayName: toLocale("finStackExt::pointStatusAlarm"),
      appId: "settingsApp",
      ignoreSettings,
      action: "finAlarmSettingsForm()",
      finForm: true,
      alarmSettings: true,
      // action:["finstack.eval('finAlarmSettingsForm()').then(function(event){",
      //         "  var tmp = function(){",
      //         "    var fcont = document.querySelector('.form-container')",
      //         "    if(fcont){",
      //         "      var numstep = fcont.querySelector(\"[type='number']\")",
      //         "      var checkbx = fcont.querySelector(\"[type='checkbox']\")",
      //         "      var alrmset = app.ReadAlarmSettings()",
      //         "      numstep.value = alrmset.pollRate",
      //         "      checkbx.checked = !alrmset.enableNotifications",
      //         "    } else{ setTimeout(tmp,200) }",
      //         "  }",
      //         "  tmp()",
      //         "})"].concat("\n"),
      icon: "icon-alarm",
      iconType: "class",
      keepOpen: true,
      ui: "html",
      minUiTarget: "phone",
      order: 4
    }
  ].toGrid
end