外观
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
| finDropOverride | Feature namespace of definitions formatted as feature:name |
| finInteraction | Map of name/value tag pairs |
funcs
def
finDropOverride
Feature namespace of definitions formatted as feature:name
meta
| def | finDropOverride |
| is | feature |
| lib | lib:finStackMobile |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
tags
| finInteraction | Map of name/value tag pairs |
def
finInteraction
Map of name/value tag pairs. See Kinds chapter.
meta
| def | finInteraction |
| is | dict |
| lib | lib:finStackMobile |
| tagOn | finDropOverride |
supertypes
| val | Data value type |
| dict | Map of name/value tag pairs |
def
func:alarmsV2Menu
alarmsV2Menu()
Axon function
meta
| def | func:alarmsV2Menu |
| finStackMobileMenu | ✓ |
| is | func |
| lib | lib:finStackMobile |
| name | alarmsV2Menu |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
}]
enddef
func:blineMenu
blineMenu()
Axon function
meta
| def | func:blineMenu |
| finStackMobileMenu | ✓ |
| is | func |
| lib | lib:finStackMobile |
| name | blineMenu |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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 +")"
}]
enddef
func:cleanFolderPathName
cleanFolderPathName(stringToClean)
Axon function
meta
| def | func:cleanFolderPathName |
| is | func |
| lib | lib:finStackMobile |
| name | cleanFolderPathName |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon function |
def
func:commonTagBundles
commonTagBundles()
Axon function
meta
| def | func:commonTagBundles |
| is | func |
| lib | lib:finStackMobile |
| name | commonTagBundles |
| overridable | ✓ |
| private | ✓ |
| tagBundleFunc | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
}
]
enddef
func:comparePointVal
comparePointVal(equipId, pointName: "Room Setpoint")
Axon function
meta
| def | func:comparePointVal |
| is | func |
| lib | lib:finStackMobile |
| name | comparePointVal |
| overridable | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon function |
src
(equipId,pointName:"Room Setpoint") => do
try read(equipRef==equipId and navName==pointName)->curVal
catch null
enddef
func:connectorPoinBadgeVal
connectorPoinBadgeVal(item)
Axon function
meta
| def | func:connectorPoinBadgeVal |
| is | func |
| lib | lib:finStackMobile |
| name | connectorPoinBadgeVal |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
func:connectorPointBadgeType
connectorPointBadgeType(item)
Axon function
meta
| def | func:connectorPointBadgeType |
| is | func |
| lib | lib:finStackMobile |
| name | connectorPointBadgeType |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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"
enddef
func:connectorPointColor
connectorPointColor(item)
Axon function
meta
| def | func:connectorPointColor |
| is | func |
| lib | lib:finStackMobile |
| name | connectorPointColor |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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 ""
enddef
func:connectorPointTooltip
connectorPointTooltip(item)
Axon function
meta
| def | func:connectorPointTooltip |
| is | func |
| lib | lib:finStackMobile |
| name | connectorPointTooltip |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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 ""
enddef
func:connectorSelectedMenu
connectorSelectedMenu(id, connType: null)
Axon function
meta
| def | func:connectorSelectedMenu |
| is | func |
| lib | lib:finStackMobile |
| name | connectorSelectedMenu |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
},
])
enddef
func:connectorsByTypeMenu
connectorsByTypeMenu(type)
Axon function
meta
| def | func:connectorsByTypeMenu |
| is | func |
| lib | lib:finStackMobile |
| name | connectorsByTypeMenu |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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})
enddef
func:connectorsDebugInfoMenu
connectorsDebugInfoMenu(connId)
Axon function
meta
| def | func:connectorsDebugInfoMenu |
| is | func |
| lib | lib:finStackMobile |
| name | connectorsDebugInfoMenu |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
func:connectorsMainMenu
connectorsMainMenu()
Axon function
meta
| def | func:connectorsMainMenu |
| finStackMobileMenu | ✓ |
| is | func |
| lib | lib:finStackMobile |
| name | connectorsMainMenu |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
}]
enddef
func:connectorsMenu
connectorsMenu(targetRef: null, viewAll: false)
Axon function
meta
| def | func:connectorsMenu |
| is | func |
| lib | lib:finStackMobile |
| name | connectorsMenu |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
func:connectorsMenuSettings
connectorsMenuSettings(viewAll: false)
Axon function
meta
| def | func:connectorsMenuSettings |
| is | func |
| lib | lib:finStackMobile |
| name | connectorsMenuSettings |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
}
enddef
func:connectorsPointIcons
connectorsPointIcons(item)
Axon function
meta
| def | func:connectorsPointIcons |
| is | func |
| lib | lib:finStackMobile |
| name | connectorsPointIcons |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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"
enddef
func:connectorsPolicyInfo
connectorsPolicyInfo(id)
Axon function
meta
| def | func:connectorsPolicyInfo |
| is | func |
| lib | lib:finStackMobile |
| name | connectorsPolicyInfo |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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"))
enddef
func:connectorsRightIcon
connectorsRightIcon(connector)
Axon function
meta
| def | func:connectorsRightIcon |
| is | func |
| lib | lib:finStackMobile |
| name | connectorsRightIcon |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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"
enddef
func:connectorsShowPoints
connectorsShowPoints(id, path: null)
Axon function
meta
| def | func:connectorsShowPoints |
| is | func |
| lib | lib:finStackMobile |
| name | connectorsShowPoints |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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)
enddef
func:connectorsTunePolicyMenu
connectorsTunePolicyMenu()
Axon function
meta
| def | func:connectorsTunePolicyMenu |
| is | func |
| lib | lib:finStackMobile |
| name | connectorsTunePolicyMenu |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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)
enddef
func:dbAddEditCommit
dbAddEditCommit(recId: null, props, folderPath: null, emptyFolderId: null)
Axon function
meta
| def | func:dbAddEditCommit |
| is | func |
| lib | lib:finStackMobile |
| name | dbAddEditCommit |
| overridable | ✓ |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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)
enddef
func:dbBuilderCreateLearnPointsJob
dbBuilderCreateLearnPointsJob(connRef, connType: "bacnet", learnPath: null)
Axon function
meta
| def | func:dbBuilderCreateLearnPointsJob |
| is | func |
| lib | lib:finStackMobile |
| name | dbBuilderCreateLearnPointsJob |
| overridable | ✓ |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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"))
enddef
func:dbBuilderDiscoverBacnetPoints
dbBuilderDiscoverBacnetPoints(connRef, jobRec, folder: null)
Axon function
meta
| def | func:dbBuilderDiscoverBacnetPoints |
| is | func |
| lib | lib:finStackMobile |
| name | dbBuilderDiscoverBacnetPoints |
| overridable | ✓ |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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)
enddef
func:dbBuilderDiscoverConnectors
dbBuilderDiscoverConnectors(discoverId: null, connType: "bacnet", useConnDiscover: false)
Axon function
meta
| def | func:dbBuilderDiscoverConnectors |
| is | func |
| lib | lib:finStackMobile |
| name | dbBuilderDiscoverConnectors |
| overridable | ✓ |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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 funcdef
func:dbBuilderDropAction
dbBuilderDropAction(dragTargets, dropTarget, treeType: "")
Axon function
meta
| def | func:dbBuilderDropAction |
| is | func |
| lib | lib:finStackMobile |
| name | dbBuilderDropAction |
| overridable | ✓ |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
func:dbBuilderSelectAction
dbBuilderSelectAction(panelOpts, selectedRef: null)
Axon function
meta
| def | func:dbBuilderSelectAction |
| is | func |
| lib | lib:finStackMobile |
| name | dbBuilderSelectAction |
| overridable | ✓ |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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] }
enddef
func:dbDiscoveryAdd
dbDiscoveryAdd(connectors, makeTemplate: false, refreshStr: "")
Axon function
meta
| def | func:dbDiscoveryAdd |
| is | func |
| lib | lib:finStackMobile |
| name | dbDiscoveryAdd |
| overridable | ✓ |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
func:dbDragActionAddConnector
dbDragActionAddConnector(dropTarget, dragItems, targetRef: null)
Axon function
meta
| def | func:dbDragActionAddConnector |
| is | func |
| lib | lib:finStackMobile |
| name | dbDragActionAddConnector |
| overridable | ✓ |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
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
| construct | dbGraphicPanels(read(site)->id, "equip") |
| def | func:dbGraphicPanels |
| is | func |
| lib | lib:finStackMobile |
| name | dbGraphicPanels |
| overridable | ✓ |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
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
| construct | dbMakeDataGridPanel("siteRef == " +read(site)->id+" and ... |
| def | func:dbMakeDataGridPanel |
| is | func |
| lib | lib:finStackMobile |
| name | dbMakeDataGridPanel |
| overridable | ✓ |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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})
enddef
func:dropActionConnectorTree
dropActionConnectorTree(dragTargets, dropTarget)
Axon function
meta
| def | func:dropActionConnectorTree |
| is | func |
| lib | lib:finStackMobile |
| name | dropActionConnectorTree |
| overridable | ✓ |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
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
| construct | dropActionEquipTree([read(equip)->id.toAxonCode], read(f... |
| def | func:dropActionEquipTree |
| is | func |
| lib | lib:finStackMobile |
| name | dropActionEquipTree |
| overridable | ✓ |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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)
enddef
func:dropActionFolderPaths
dropActionFolderPaths(dragTargets, dropTarget, treeTag)
Axon function
meta
| def | func:dropActionFolderPaths |
| is | func |
| lib | lib:finStackMobile |
| name | dropActionFolderPaths |
| overridable | ✓ |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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 funcdef
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
| construct | dropActionSavedFiltersTree([read(tagBundle)->id.toAxonCo... |
| def | func:dropActionSavedFiltersTree |
| is | func |
| lib | lib:finStackMobile |
| name | dropActionSavedFiltersTree |
| overridable | ✓ |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
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
| construct | dropActionScheduleTree([read(equip)->id.toAxonCode], rea... |
| def | func:dropActionScheduleTree |
| is | func |
| lib | lib:finStackMobile |
| name | dropActionScheduleTree |
| overridable | ✓ |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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)
enddef
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
| construct | dropActionTagBundlesTree([read(equip)->id.toAxonCode], r... |
| def | func:dropActionTagBundlesTree |
| is | func |
| lib | lib:finStackMobile |
| name | dropActionTagBundlesTree |
| overridable | ✓ |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
func:finAddBuilderProps
finAddBuilderProps(treeDataGrid, treeDis, branchDis)
Axon function
meta
| def | func:finAddBuilderProps |
| is | func |
| lib | lib:finStackMobile |
| name | finAddBuilderProps |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon function |
def
func:finAddPointInfo
finAddPointInfo(newRefs)
Axon function
meta
| def | func:finAddPointInfo |
| is | func |
| lib | lib:finStackMobile |
| name | finAddPointInfo |
| overridable | ✓ |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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")
enddef
func:finAlarmSettingsForm
finAlarmSettingsForm(pollRate: 0, disableNotifications: true)
Axon function
meta
| def | func:finAlarmSettingsForm |
| is | func |
| lib | lib:finStackMobile |
| name | finAlarmSettingsForm |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
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
| construct | finApplyTagBundle(read(tagBundle), read(floor)) |
| def | func:finApplyTagBundle |
| is | func |
| lib | lib:finStackMobile |
| name | finApplyTagBundle |
| overridable | ✓ |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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 funcdef
func:finBackupRecordForm
finBackupRecordForm(selected: null)
Axon function
meta
| def | func:finBackupRecordForm |
| is | func |
| lib | lib:finStackMobile |
| name | finBackupRecordForm |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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()})
enddef
func:finBackupUploadForm
finBackupUploadForm(selected: null)
Axon function
meta
| def | func:finBackupUploadForm |
| is | func |
| lib | lib:finStackMobile |
| name | finBackupUploadForm |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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()})
enddef
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
| construct | finBlocks() |
| def | func:finBlocks |
| is | func |
| lib | lib:finStackMobile |
| name | finBlocks |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
func:finBlocksJavaScript
finBlocksJavaScript()
Axon function
meta
| def | func:finBlocksJavaScript |
| is | func |
| lib | lib:finStackMobile |
| name | finBlocksJavaScript |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon function |
src
() => do
ioReadTrio(`fan://finStackMobileExt/libs/finBlocksJavaScript.trio`)
enddef
func:finBlocksPpcl
finBlocksPpcl()
Axon function
meta
| def | func:finBlocksPpcl |
| is | func |
| lib | lib:finStackMobile |
| name | finBlocksPpcl |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon function |
src
() => do
ioReadTrio(`fan://finStackMobileExt/libs/finBlocksPpcl.trio`)
enddef
func:finBreadcrumbs
finBreadcrumbs(treeType: "equip", targetRef: null, maxLevels: null)
Axon function
meta
| def | func:finBreadcrumbs |
| is | func |
| lib | lib:finStackMobile |
| name | finBreadcrumbs |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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)
enddef
func:finBuilderContextMenuItems
finBuilderContextMenuItems()
Axon function
meta
| def | func:finBuilderContextMenuItems |
| finBuilderMenu | ✓ |
| is | func |
| lib | lib:finStackMobile |
| name | finBuilderContextMenuItems |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
func:finBuilderEquipTrash
finBuilderEquipTrash(recs)
Axon function
meta
| def | func:finBuilderEquipTrash |
| is | func |
| lib | lib:finStackMobile |
| name | finBuilderEquipTrash |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon function |
def
func:finClimbNavTree
finClimbNavTree(curType, targetRef)
Axon function
meta
| def | func:finClimbNavTree |
| is | func |
| lib | lib:finStackMobile |
| name | finClimbNavTree |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
func:finCommonQueries
finCommonQueries()
Axon function
meta
| def | func:finCommonQueries |
| is | func |
| lib | lib:finStackMobile |
| name | finCommonQueries |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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)
enddef
func:finConstructBasicTreeItem
finConstructBasicTreeItem(record, treeDis, branchDis, treeInfo)
Axon function
meta
| def | func:finConstructBasicTreeItem |
| is | func |
| lib | lib:finStackMobile |
| name | finConstructBasicTreeItem |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
| def | func:finContentOnFunc |
| is | func |
| lib | lib:finStackMobile |
| name | finContentOnFunc |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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: ""}
enddef
func:finCreateFolder
finCreateFolder(folderName, treeTag, parentFolderPath: null, childId: null)
Axon function
meta
| def | func:finCreateFolder |
| is | func |
| lib | lib:finStackMobile |
| name | finCreateFolder |
| overridable | ✓ |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
func:finCreateFolderPath
finCreateFolderPath(id: null, filterFor)
Axon function
meta
| def | func:finCreateFolderPath |
| is | func |
| lib | lib:finStackMobile |
| name | finCreateFolderPath |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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()})
enddef
func:finCreateProjectForm
finCreateProjectForm(preFill: null)
Axon function
meta
| def | func:finCreateProjectForm |
| is | func |
| lib | lib:finStackMobile |
| name | finCreateProjectForm |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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()})
enddef
func:finDBCreateNewEquipCommit
finDBCreateNewEquipCommit(equipName, navKind, parent: null, pointSettings: null)
Axon function
meta
| def | func:finDBCreateNewEquipCommit |
| is | func |
| lib | lib:finStackMobile |
| name | finDBCreateNewEquipCommit |
| overridable | ✓ |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
func:finDbBuilderMenuItem
finDbBuilderMenuItem()
Axon function
meta
| def | func:finDbBuilderMenuItem |
| finStackMobileMenu | ✓ |
| is | func |
| lib | lib:finStackMobile |
| name | finDbBuilderMenuItem |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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,
}
]
enddef
func:finDbHaystackFindUniqueEquipTypes
finDbHaystackFindUniqueEquipTypes(conn, filter, percentMatch, applyTags, tag)
Axon function
meta
| def | func:finDbHaystackFindUniqueEquipTypes |
| is | func |
| lib | lib:finStackMobile |
| name | finDbHaystackFindUniqueEquipTypes |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon function |
def
func:finDbHaystackNodeSelectAction
finDbHaystackNodeSelectAction(queryStr, nodeTypeStr)
Axon function
meta
| def | func:finDbHaystackNodeSelectAction |
| is | func |
| lib | lib:finStackMobile |
| name | finDbHaystackNodeSelectAction |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon function |
def
func:finDbHaystackReadAllPoints
finDbHaystackReadAllPoints(connectorRef, branchFilter, iteration)
Axon function
meta
| def | func:finDbHaystackReadAllPoints |
| is | func |
| lib | lib:finStackMobile |
| name | finDbHaystackReadAllPoints |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon function |
def
func:finDbRelationshipAddEdit
finDbRelationshipAddEdit(curItem: null, folderPath: null)
Axon function
meta
| dbAddEdit | ✓ |
| def | func:finDbRelationshipAddEdit |
| is | func |
| lib | lib:finStackMobile |
| name | finDbRelationshipAddEdit |
| private | ✓ |
| relationshipTree | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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}"
}
enddef
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
| construct | finDbSavedFiltersTreeSelectAction() |
| def | func:finDbSavedFiltersTreeSelectAction |
| is | func |
| lib | lib:finStackMobile |
| name | finDbSavedFiltersTreeSelectAction |
| overridable | ✓ |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
}
]
}
enddef
func:finDbSavedQueryFilterAddEdit
finDbSavedQueryFilterAddEdit(curItem: null, folderPath: null)
Axon function
meta
| dbAddEdit | ✓ |
| def | func:finDbSavedQueryFilterAddEdit |
| is | func |
| lib | lib:finStackMobile |
| name | finDbSavedQueryFilterAddEdit |
| overridable | ✓ |
| private | ✓ |
| savedQueryFilterTree | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
}
enddef
func:finDbTagBundleAddEdit
finDbTagBundleAddEdit(curItem: null, folderPath: null)
Axon function
meta
| dbAddEdit | ✓ |
| def | func:finDbTagBundleAddEdit |
| is | func |
| lib | lib:finStackMobile |
| name | finDbTagBundleAddEdit |
| overridable | ✓ |
| private | ✓ |
| tagBundleTree | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
}
enddef
func:finDbTemplateAddEdit
finDbTemplateAddEdit(curItem: null, folderPath: null)
Axon function
meta
| dbAddEdit | ✓ |
| def | func:finDbTemplateAddEdit |
| is | func |
| lib | lib:finStackMobile |
| name | finDbTemplateAddEdit |
| private | ✓ |
| templateTree | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
}
enddef
func:finDbTopicAdd
finDbTopicAdd(folderPath: null)
Axon function
meta
| def | func:finDbTopicAdd |
| is | func |
| lib | lib:finStackMobile |
| name | finDbTopicAdd |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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()})
enddef
func:finEquipCharts
finEquipCharts(equ, rng: today)
Function to generate chart for equip with schedules and alarms. Alpha Release.
meta
| chartOn | equip and not baId and not hidden |
| def | func:finEquipCharts |
| dis | FinEquipCharts |
| excludes | systemOne |
| finSavedChart | ✓ |
| is | func |
| lib | lib:finStackMobile |
| name | finEquipCharts |
| private | ✓ |
| queryString | finEquipCharts($targetRef) |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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.parseDiscretePeriodsdef
func:finEquipRefTree
finEquipRefTree(id, treePath: null)
Axon function
meta
| def | func:finEquipRefTree |
| is | func |
| lib | lib:finStackMobile |
| name | finEquipRefTree |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
func:finExtSettingsForm
finExtSettingsForm(data: null)
Axon function
meta
| def | func:finExtSettingsForm |
| is | func |
| lib | lib:finStackMobile |
| name | finExtSettingsForm |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
func:finFavoritesForm
finFavoritesForm(newnotremove: true, url: null, data: null)
Axon function
meta
| def | func:finFavoritesForm |
| is | func |
| lib | lib:finStackMobile |
| name | finFavoritesForm |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
func:finFavoritesMenu
finFavoritesMenu(target: null)
Axon function
meta
| def | func:finFavoritesMenu |
| finStackMobileMenu | ✓ |
| is | func |
| lib | lib:finStackMobile |
| name | finFavoritesMenu |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
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
| construct | finFindNonDbRec(readAll(site).colToList("id")) |
| def | func:finFindNonDbRec |
| is | func |
| lib | lib:finStackMobile |
| name | finFindNonDbRec |
| overridable | ✓ |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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)
enddef
func:finFindToolsOnNavItem
finFindToolsOnNavItem(navItemRefs: null)
Axon function
meta
| def | func:finFindToolsOnNavItem |
| is | func |
| lib | lib:finStackMobile |
| name | finFindToolsOnNavItem |
| overridable | ✓ |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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+"}])"
}
)
enddef
func:finFolioDownloadForm
finFolioDownloadForm(data: null, app: null)
Form to download records with a certain filter, like legacy Folio Download
meta
| appFormOn | folio |
| def | func:finFolioDownloadForm |
| dis | toLocale("finStackExt::reportsDownload") |
| folderPath | toLocale("finStackMobileExt::coreBackup") |
| is | func |
| lib | lib:finStackMobile |
| name | finFolioDownloadForm |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
func:finFolioMenu
finFolioMenu()
Axon function
meta
| def | func:finFolioMenu |
| finStackMobileMenu | ✓ |
| is | func |
| lib | lib:finStackMobile |
| name | finFolioMenu |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
func:finFolioSettings
finFolioSettings(stage, inp: null)
Axon function
meta
| def | func:finFolioSettings |
| is | func |
| lib | lib:finStackMobile |
| name | finFolioSettings |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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() }
enddef
func:finFolioUploadForm
finFolioUploadForm(stage: null, data: null, app: null)
Form to upload records through file or through text, like legacy Folio Import
meta
| appFormOn | folio |
| def | func:finFolioUploadForm |
| dis | toLocale("finStackExt::upload") |
| folderPath | toLocale("finStackMobileExt::coreBackup") |
| is | func |
| lib | lib:finStackMobile |
| name | finFolioUploadForm |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
func:finFormAddEditHaystackConnector
finFormAddEditHaystackConnector(haystackConnRef: null, refill: null, folderPath: null)
Axon function
meta
| def | func:finFormAddEditHaystackConnector |
| is | func |
| lib | lib:finStackMobile |
| name | finFormAddEditHaystackConnector |
| overridable | ✓ |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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()})
enddef
func:finFormBacnetConnDiscoverSettings
finFormBacnetConnDiscoverSettings(refill: null)
Axon function
meta
| def | func:finFormBacnetConnDiscoverSettings |
| is | func |
| lib | lib:finStackMobile |
| name | finFormBacnetConnDiscoverSettings |
| overridable | ✓ |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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()})
enddef
func:finFormCloneConnector
finFormCloneConnector(selectedTargets, curType: "bacnet", curContext: null, reopen: false, jsAction: "")
Axon function
meta
| def | func:finFormCloneConnector |
| is | func |
| lib | lib:finStackMobile |
| name | finFormCloneConnector |
| overridable | ✓ |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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()})
enddef
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
| construct | finFormConfirmChangesAlert("readAll(site)", "Read all si... |
| def | func:finFormConfirmChangesAlert |
| is | func |
| lib | lib:finStackMobile |
| name | finFormConfirmChangesAlert |
| overridable | ✓ |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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()})
enddef
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
| def | func:finFormDBAddEdit |
| is | func |
| lib | lib:finStackMobile |
| name | finFormDBAddEdit |
| overridable | ✓ |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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))
enddef
func:finFormDBBuilderDelete
finFormDBBuilderDelete(selectedItem, customAction: null, customMsg: null, itemTree: null, folderPath: "")
Axon function
meta
| def | func:finFormDBBuilderDelete |
| is | func |
| lib | lib:finStackMobile |
| name | finFormDBBuilderDelete |
| overridable | ✓ |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
func:finFormDBCreateNewEquip
finFormDBCreateNewEquip(parentNav, parentId: null, equipNav: "", reopen: false)
Axon function
meta
| def | func:finFormDBCreateNewEquip |
| is | func |
| lib | lib:finStackMobile |
| name | finFormDBCreateNewEquip |
| overridable | ✓ |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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()})
enddef
func:finFormDBSelectEditDelete
finFormDBSelectEditDelete(details, folderPath: "", targetRef: null)
Axon function
meta
| def | func:finFormDBSelectEditDelete |
| is | func |
| lib | lib:finStackMobile |
| name | finFormDBSelectEditDelete |
| overridable | ✓ |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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()})
enddef
func:finFormEditSchedule
finFormEditSchedule(id: null, folderPath: null)
Form to edit schedules.
meta
| def | func:finFormEditSchedule |
| dis | toLocale("finStackMobileExt::scheduleMenuEditTip") |
| is | func |
| lib | lib:finStackMobile |
| name | finFormEditSchedule |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
func:finFormManualAddEditBacnet
finFormManualAddEditBacnet(curConn: null, refill: null, connType: "ip", folderPath: null)
Axon function
meta
| def | func:finFormManualAddEditBacnet |
| is | func |
| lib | lib:finStackMobile |
| name | finFormManualAddEditBacnet |
| overridable | ✓ |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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()})
enddef
func:finFormManualOverrideAuto
finFormManualOverrideAuto(targetRef, autoAll: true, level: 8)
Axon function
meta
| def | func:finFormManualOverrideAuto |
| is | func |
| lib | lib:finStackMobile |
| name | finFormManualOverrideAuto |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
func:finFormNewHaystackPassword
finFormNewHaystackPassword(haystackConnRef, changesDict)
Axon function
meta
| def | func:finFormNewHaystackPassword |
| is | func |
| lib | lib:finStackMobile |
| name | finFormNewHaystackPassword |
| overridable | ✓ |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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()})
enddef
func:finFormRunToolsOnMulti
finFormRunToolsOnMulti(id, reopened: false)
Axon function
meta
| def | func:finFormRunToolsOnMulti |
| is | func |
| lib | lib:finStackMobile |
| name | finFormRunToolsOnMulti |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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()})
enddef
func:finFormSchedulePointPriority
finFormSchedulePointPriority(ids, prio: null)
Axon function
meta
| def | func:finFormSchedulePointPriority |
| is | func |
| lib | lib:finStackMobile |
| name | finFormSchedulePointPriority |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
func:finFormSelectBacnetType
finFormSelectBacnetType(folderPath: null)
Axon function
meta
| def | func:finFormSelectBacnetType |
| is | func |
| lib | lib:finStackMobile |
| name | finFormSelectBacnetType |
| overridable | ✓ |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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()})
enddef
func:finFormSelectTool
finFormSelectTool(id, selected, advanced, reopened: false)
Axon function
meta
| def | func:finFormSelectTool |
| is | func |
| lib | lib:finStackMobile |
| name | finFormSelectTool |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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()})
enddef
func:finFormSetConnectorDefWriteLevel
finFormSetConnectorDefWriteLevel(connectorIds: [])
Axon function
meta
| def | func:finFormSetConnectorDefWriteLevel |
| is | func |
| lib | lib:finStackMobile |
| name | finFormSetConnectorDefWriteLevel |
| overridable | ✓ |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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()})
enddef
func:finFormSetSummaryPointOrder
finFormSetSummaryPointOrder(summaryName, summariesToRunOn: null, pointsInEquip: null, equipFilter: null)
Axon function
meta
| def | func:finFormSetSummaryPointOrder |
| is | func |
| lib | lib:finStackMobile |
| name | finFormSetSummaryPointOrder |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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()})
enddef
func:finGetPods
finGetPods(podName)
Axon function
meta
| def | func:finGetPods |
| is | func |
| lib | lib:finStackMobile |
| name | finGetPods |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
| def | func:finGetPointIcon |
| is | func |
| lib | lib:finStackMobile |
| name | finGetPointIcon |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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"
enddef
func:finGetTileOn
finGetTileOn(floor)
Axon function
meta
| def | func:finGetTileOn |
| is | func |
| lib | lib:finStackMobile |
| name | finGetTileOn |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
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
| def | func:finGraphicTopLevel |
| is | func |
| lib | lib:finStackMobile |
| name | finGraphicTopLevel |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
func:finGraphicTopLevelDeleteConfirmForm
finGraphicTopLevelDeleteConfirmForm(graphicId, targetRef: null)
Axon function
meta
| def | func:finGraphicTopLevelDeleteConfirmForm |
| is | func |
| lib | lib:finStackMobile |
| name | finGraphicTopLevelDeleteConfirmForm |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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()})
enddef
func:finGraphicsGenericBindings
finGraphicsGenericBindings(glist, type)
Axon function
meta
| def | func:finGraphicsGenericBindings |
| is | func |
| lib | lib:finStackMobile |
| name | finGraphicsGenericBindings |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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)
enddef
func:finGraphicsGenericBindingsForm
finGraphicsGenericBindingsForm(tref: null)
Axon function
meta
| def | func:finGraphicsGenericBindingsForm |
| is | func |
| lib | lib:finStackMobile |
| name | finGraphicsGenericBindingsForm |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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 //finGetTargetPointdef
func:finGraphicsGenericBindingsResults
finGraphicsGenericBindingsResults(fail)
Axon function
meta
| def | func:finGraphicsGenericBindingsResults |
| is | func |
| lib | lib:finStackMobile |
| name | finGraphicsGenericBindingsResults |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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()})
enddef
func:finGraphicsUpdateThumbs
finGraphicsUpdateThumbs(stage: null, data: null)
Form to change the thumbnails on graphics
meta
| def | func:finGraphicsUpdateThumbs |
| is | func |
| lib | lib:finStackMobile |
| name | finGraphicsUpdateThumbs |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
func:finHasSpecialChars
finHasSpecialChars(stringToCheck)
Axon function
meta
| def | func:finHasSpecialChars |
| is | func |
| lib | lib:finStackMobile |
| name | finHasSpecialChars |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon function |
def
func:finHeaderAddEditMenu
finHeaderAddEditMenu(idnex: null)
Axon function
meta
| def | func:finHeaderAddEditMenu |
| is | func |
| lib | lib:finStackMobile |
| name | finHeaderAddEditMenu |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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(),
})
enddef
func:finHeaderAddEditSubMenu
finHeaderAddEditSubMenu(parnt: null, idnex: null)
Axon function
meta
| def | func:finHeaderAddEditSubMenu |
| is | func |
| lib | lib:finStackMobile |
| name | finHeaderAddEditSubMenu |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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(),
}
]
enddef
func:finHeaderButtonBadgeForm
finHeaderButtonBadgeForm(parnt, child: null)
Axon function
meta
| def | func:finHeaderButtonBadgeForm |
| is | func |
| lib | lib:finStackMobile |
| name | finHeaderButtonBadgeForm |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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()})
enddef
func:finHeaderButtonIconForm
finHeaderButtonIconForm(parnt, child: null, data: null)
Axon function
meta
| def | func:finHeaderButtonIconForm |
| is | func |
| lib | lib:finStackMobile |
| name | finHeaderButtonIconForm |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
func:finHeaderButtonLinkForm
finHeaderButtonLinkForm(parnt, child: null, data: null)
Axon function
meta
| def | func:finHeaderButtonLinkForm |
| is | func |
| lib | lib:finStackMobile |
| name | finHeaderButtonLinkForm |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
func:finHeaderButtonNameForm
finHeaderButtonNameForm(parnt, child: null)
Axon function
meta
| def | func:finHeaderButtonNameForm |
| is | func |
| lib | lib:finStackMobile |
| name | finHeaderButtonNameForm |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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()})
enddef
func:finHeaderButtonSecurityForm
finHeaderButtonSecurityForm(parnt, child: null)
Axon function
meta
| def | func:finHeaderButtonSecurityForm |
| is | func |
| lib | lib:finStackMobile |
| name | finHeaderButtonSecurityForm |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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()})
enddef
func:finHeaderForm
finHeaderForm(stage: null, data: null)
Axon function
meta
| def | func:finHeaderForm |
| deprecated | ✓ |
| is | func |
| lib | lib:finStackMobile |
| name | finHeaderForm |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
func:finHeaderFuncs
finHeaderFuncs(stage: null, data: null)
Backend functions for finHeaderForm function
meta
| def | func:finHeaderFuncs |
| deprecated | ✓ |
| is | func |
| lib | lib:finStackMobile |
| name | finHeaderFuncs |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
func:finHeaderHomeForm
finHeaderHomeForm(data: null)
Axon function
meta
| def | func:finHeaderHomeForm |
| is | func |
| lib | lib:finStackMobile |
| name | finHeaderHomeForm |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
func:finHeaderMenu
finHeaderMenu(target: null)
Axon function
meta
| def | func:finHeaderMenu |
| is | func |
| lib | lib:finStackMobile |
| name | finHeaderMenu |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
func:finHeaderReorderFunc
finHeaderReorderFunc(idnex, child: null, dir)
Axon function
meta
| def | func:finHeaderReorderFunc |
| is | func |
| lib | lib:finStackMobile |
| name | finHeaderReorderFunc |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
func:finHeaderReorderMenu
finHeaderReorderMenu()
Axon function
meta
| def | func:finHeaderReorderMenu |
| is | func |
| lib | lib:finStackMobile |
| name | finHeaderReorderMenu |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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(),
})
enddef
func:finHeaderReorderSubMenu
finHeaderReorderSubMenu(idnex)
Axon function
meta
| def | func:finHeaderReorderSubMenu |
| is | func |
| lib | lib:finStackMobile |
| name | finHeaderReorderSubMenu |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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(),
})
enddef
func:finHostChangePassForm
finHostChangePassForm(uname)
Axon function
meta
| def | func:finHostChangePassForm |
| is | func |
| lib | lib:finStackMobile |
| name | finHostChangePassForm |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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()})
enddef
func:finHostMainMenu
finHostMainMenu()
Axon function
meta
| def | func:finHostMainMenu |
| finStackMobileMenu | ✓ |
| is | func |
| lib | lib:finStackMobile |
| name | finHostMainMenu |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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 []
enddef
func:finHostUpdateLicenseForm
finHostUpdateLicenseForm(uname, data: null)
Axon function
meta
| def | func:finHostUpdateLicenseForm |
| is | func |
| lib | lib:finStackMobile |
| name | finHostUpdateLicenseForm |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
func:finHostUsageForm
finHostUsageForm()
Axon function
meta
| def | func:finHostUsageForm |
| is | func |
| lib | lib:finStackMobile |
| name | finHostUsageForm |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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()})
enddef
func:finInfoMenu
finInfoMenu(isSiemens: "")
Axon function
meta
| def | func:finInfoMenu |
| finStackMobileMenu | ✓ |
| is | func |
| lib | lib:finStackMobile |
| name | finInfoMenu |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
func:finInjectableProgramResources
finInjectableProgramResources()
Axon function
meta
| def | func:finInjectableProgramResources |
| finRemoteResource | ✓ |
| is | func |
| lib | lib:finStackMobile |
| name | finInjectableProgramResources |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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`"}
]
enddef
func:finJobMenu
finJobMenu()
Axon function
meta
| def | func:finJobMenu |
| finStackMobileMenu | ✓ |
| is | func |
| lib | lib:finStackMobile |
| name | finJobMenu |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
func:finJobSettings
finJobSettings(stage, inp: null)
Axon function
meta
| def | func:finJobSettings |
| is | func |
| lib | lib:finStackMobile |
| name | finJobSettings |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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() }
enddef
func:finManualAddEditBacnetCommit
finManualAddEditBacnetCommit(props, connType, connRef: null, folderPath: null)
Axon function
meta
| def | func:finManualAddEditBacnetCommit |
| is | func |
| lib | lib:finStackMobile |
| name | finManualAddEditBacnetCommit |
| overridable | ✓ |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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]))
enddef
func:finMobileHardDelete
finMobileHardDelete(ids)
Axon function
meta
| baSuExec | ✓ |
| def | func:finMobileHardDelete |
| is | func |
| lib | lib:finStackMobile |
| name | finMobileHardDelete |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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)
enddef
func:finNavListChildren
finNavListChildren(query, folderPath, returnCount, addPoints)
Axon function
meta
| def | func:finNavListChildren |
| is | func |
| lib | lib:finStackMobile |
| name | finNavListChildren |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon function |
def
func:finNavTreeDropOverrides
finNavTreeDropOverrides()
Axon function
meta
| def | func:finNavTreeDropOverrides |
| is | func |
| lib | lib:finStackMobile |
| name | finNavTreeDropOverrides |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon function |
def
func:finNavTreeTypes
finNavTreeTypes(forDbTrees, searchDict)
Axon function
meta
| def | func:finNavTreeTypes |
| is | func |
| lib | lib:finStackMobile |
| name | finNavTreeTypes |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon function |
def
func:finOMAddForm
finOMAddForm(stage: null, data: null, target: null)
Axon function
meta
| def | func:finOMAddForm |
| is | func |
| lib | lib:finStackMobile |
| name | finOMAddForm |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
func:finOMContentOnForm
finOMContentOnForm(id, act, stage: null)
Axon function
meta
| def | func:finOMContentOnForm |
| is | func |
| lib | lib:finStackMobile |
| name | finOMContentOnForm |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
func:finOMDeleteForm
finOMDeleteForm(id, act)
Axon function
meta
| def | func:finOMDeleteForm |
| is | func |
| lib | lib:finStackMobile |
| name | finOMDeleteForm |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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()})
enddef
func:finOMMenu
finOMMenu(target: null)
Axon function
meta
| def | func:finOMMenu |
| finStackMobileMenu | ✓ |
| is | func |
| lib | lib:finStackMobile |
| name | finOMMenu |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
func:finOMMenu2
finOMMenu2(target: null, all: null)
Axon function
meta
| def | func:finOMMenu2 |
| is | func |
| lib | lib:finStackMobile |
| name | finOMMenu2 |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
func:finOMMenu3
finOMMenu3(target: null, all: null, type: null)
Axon function
meta
| def | func:finOMMenu3 |
| is | func |
| lib | lib:finStackMobile |
| name | finOMMenu3 |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
func:finProjectAuditForm
finProjectAuditForm(data: null)
Axon function
meta
| def | func:finProjectAuditForm |
| is | func |
| lib | lib:finStackMobile |
| name | finProjectAuditForm |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
func:finProjectCategoryForm
finProjectCategoryForm(data: null, err: null)
Axon function
meta
| def | func:finProjectCategoryForm |
| is | func |
| lib | lib:finStackMobile |
| name | finProjectCategoryForm |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
func:finProjectEmailForm
finProjectEmailForm(data: null)
Axon function
meta
| def | func:finProjectEmailForm |
| is | func |
| lib | lib:finStackMobile |
| name | finProjectEmailForm |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
func:finProjectProjectForm
finProjectProjectForm()
Axon function
meta
| def | func:finProjectProjectForm |
| is | func |
| lib | lib:finStackMobile |
| name | finProjectProjectForm |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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()})
enddef
func:finQueries
finQueries()
Axon function
meta
| def | func:finQueries |
| finCommonQuery | ✓ |
| is | func |
| lib | lib:finStackMobile |
| name | finQueries |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
func:finReadByIdTrash
finReadByIdTrash(id, checked)
Axon function
meta
| def | func:finReadByIdTrash |
| is | func |
| lib | lib:finStackMobile |
| name | finReadByIdTrash |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon function |
def
func:finReadByIdsTrash
finReadByIdsTrash(ids, checked)
Axon function
meta
| def | func:finReadByIdsTrash |
| is | func |
| lib | lib:finStackMobile |
| name | finReadByIdsTrash |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon function |
def
func:finReadCsvWithEmbeddedDelimeter
finReadCsvWithEmbeddedDelimeter(csvSource, delimeter)
Axon function
meta
| def | func:finReadCsvWithEmbeddedDelimeter |
| is | func |
| lib | lib:finStackMobile |
| name | finReadCsvWithEmbeddedDelimeter |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
| def | func:finReadHeader |
| is | func |
| lib | lib:finStackMobile |
| name | finReadHeader |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
| def | func:finRestartFinstack |
| is | func |
| lib | lib:finStackMobile |
| name | finRestartFinstack |
| su | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon function |
def
func:finRunSelectedTool
finRunSelectedTool(id, targets, tool)
Axon function
meta
| def | func:finRunSelectedTool |
| is | func |
| lib | lib:finStackMobile |
| name | finRunSelectedTool |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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)
enddef
func:finSettingsMenu
finSettingsMenu()
Axon function
meta
| def | func:finSettingsMenu |
| finStackMobileMenu | ✓ |
| is | func |
| lib | lib:finStackMobile |
| name | finSettingsMenu |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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
enddef
func:finSettingsMenuLegacy
finSettingsMenuLegacy()
Axon function
meta
| def | func:finSettingsMenuLegacy |
| is | func |
| lib | lib:finStackMobile |
| name | finSettingsMenuLegacy |
| private | ✓ |
supertypes
| feature | Feature namespace of definitions formatted as feature:name |
| func | Axon 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