Data Model
This a an example of a data model definition. It is used both by the backend and frontend.
@validity
class Asset {
@propertyTitle('Id')
let id: Int
@propertyTitle('Fullname')
let fullname: Char<255>
@propertyTitle('Name')
let name: Char<255>
@propertyTitle('Operating System')
let os: Char<255>
@propertyTitle('Status')
let status: Char<255>
@propertyTitle('Company')
let company: Char<255>
@propertyTitle('Environment')
let environment: Char<255>
@propertyTitle('Install Date')
let installDate: Char<255>
}
Pattern
This is an example of a pattern definition that is used by a server to parse an Excel file pattern into a database.
[
RecordPattern(
pattern: 'assets\/\(orgCode)_Assets_(\d+)\.xlsx',
pathData: (pathData: [String]) -> {
[validFrom: Date(pathData[0], options: [['yyyyMMdd']])]
},
processRecord: (storage: RecordStorage, record: [String], orgCode: String, pathData: [String: Node]) -> {
let asset = Asset()
asset._orgCode = orgCode
asset._validFrom = pathData['validFrom']
var fullname, installDate: String
RecordPattern.parse(record, \.asset.id, \.fullname, \.asset.os, \.asset.status, \.asset.company,
\.asset.environment, \.installDate)
asset.fullname = fullname.lowercase
asset.name = fullname.regexp('([^[.]]+).*')
asset.installDate = installDate.parseDatetime([['yyyy-MM-dd HH:mm:ss']])
storage.store(asset)
})
]
Page
This is an example of a page definition. It is used in the Nodelab frontend to generate pages and menus.
@pathClass(Asset)
class AssetsDashboard: Page {
state date = QueryState<String>(valuesQuery: Query(
scripts: ['\._validFrom/'],
orderScripts: ['\._validFrom/'],
limit: 1000,
isDistinct: true
))"
state assetCount = QueryState<Int>(Query(
scripts: ['\._orgCode..count/'],
filters: [
'\._validFrom/=="\(date)"',
'\.status/=="In use"'
]
))
state os = QueryState<[String]>(valuesQuery: Query(
scripts: ['\.os/'],
orderScripts: ['\.os/'],
limit: 100,
isDistinct: true
))
state status = QueryState<[String]>(valuesQuery: Query(
scripts: ['\.status/'],
orderScripts: ['\.status/'],
limit: 100,
isDistinct: true
))
state environment = QueryState<[String]>(valuesQuery: Query(
scripts: ['\.environment/'],
orderScripts: ['\.environment/'],
limit: 100,
isDistinct: true
))
state compareDate = QueryState<Date>(valuesQuery: Query(
scripts: ['\._validFrom/'],
orderScripts: ['\._validFrom/'],
limit: 1000,
isDistinct: true
))
init() {
super(
VStack(
HStack(
StateSelector(\.date, title: 'Date', titleScript: '\._validFrom/', defaultSelectionIndex: 0, css: 'col-md-2'),
StateSelector(\.os, title: 'OS', titleScript: '\.os/', css: 'col-md-3'),
StateSelector(\.status, title: 'Status', titleScript: '\.status/', css: 'col-md-2'),
StateSelector(\.environment, title: 'Environment', titleScript: '\.environment/', css: 'col-md-3'),
StateSelector(\.compareDate, title: 'Compare Date', titleScript: '\._validFrom/', css: 'col-md-2')
),
HStack(
TextView(
title: 'Assets in use',
mdText: '\(assetCount .% \'%d\')',
mdFontId: 'assetCount',
css: 'col-md-3'
),
BarChart(
title: 'Operating System',
barScript: '\.os/',
splitScript: '\.status/',
valueScript: '\._orgCode..count/',
statePath: \.os,
query: Query(
filters: ['\._validFrom/=="\(date)"'],
orderScripts: ['\.os/']
),
emHeight: 16,
css: 'col-md-3'
),
PieChart(
title: 'Status',
pieScript: '\.status/',
valueScript: '\._orgCode..count/',
statePath: \.status,
query: Query(
filters: ['\._validFrom/=="\(date)"'],
orderScripts: ['\.status/']
),
emHeight: 16,
css: 'col-md-3'
),
PieChart(
title: 'Environment',
pieScript: '\.environment/',
valueScript: '\._orgCode..count/',
statePath: \.environment,
query: Query(
filters: ['\._validFrom/=="\(date)"'],
orderScripts: ['\.environment/']
),
emHeight: 16,
css: 'col-md-3'
)
),
Table(
title: 'List of Assets',
titles: ['Date', 'Server Name', 'OS', 'Environment', 'Status', '\(if compareDate "Status \(compareDate)")'],
hasNumbering: true,
query:
@edgeSpaces([
EdgeSpace(Asset, name: 'comp', filters: ['\comp._validFrom/=="\(compareDate)"'])
])
Query(
scripts: ['\._validFrom/', '\.name/', '\.os/', '\.environment/', '\.status/', '\(if compareDate "\comp.status/")'],
filters: [
'\._validFrom/=="\(date)"',
'\(if os "\(os).contains(\.os/)")',
'\(if status "\(status).contains(\.status/)")',
'\(if environment "\(environment).contains(\.environment/)")'],
orderScripts: ['\.name/'],
limit: 1000,
maxClassCount: 2
),
emHeight: 16,
css: 'col-md-12'
)
)
).withFont(Font('assetCount', size: '8em', align: 'center'))
}
}
The code above result in a page like this in the Nodelab product: