Data Model
This a an example of a data model definition. It is used both by the backend and frontend.
@validity class Asset: DataRecord { @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.
@edgeSpaces([ EdgeSpace(Asset) ]) class AssetsDashboard: Page { state date = QueryState<String>(valuesQuery: Query( paths: [\._validFrom], orderPaths: [\._validFrom], limit: 1000, isDistinct: true )) state assetCount = QueryState<Int>(Query( paths: [\._orgCode..count], filters: [ '_validFrom==\'\(date)\'', "status=='In use'" ] )) state os = QueryState<[String]>(valuesQuery: Query( paths: [\.os], orderPaths: [\.os], limit: 100, isDistinct: true )) state status = QueryState<[String]>(valuesQuery: Query( paths: [\.status], orderPaths: [\.status], limit: 100, isDistinct: true )) state environment = QueryState<[String]>(valuesQuery: Query( paths: [\.environment], orderPaths: [\.environment], limit: 100, isDistinct: true )) state compareDate = QueryState<Date>(valuesQuery: Query( paths: [\._validFrom], orderPaths: [\._validFrom], limit: 1000, isDistinct: true )) @edgeSpaces([ EdgeSpace(Asset, name: 'comp', filters: ['comp._validFrom=="\(compareDate)"']) ]) init() { super( VStack( HStack( StateSelector(\.date, title: 'Date', titlePath: \._validFrom, defaultSelectionIndex: 0, css: 'col-md-2'), StateSelector(\.os, title: 'OS', titlePath: \.os, css: 'col-md-3'), StateSelector(\.status, title: 'Status', titlePath: \.status, css: 'col-md-2'), StateSelector(\.environment, title: 'Environment', titlePath: \.environment, css: 'col-md-3'), StateSelector(\.compareDate, title: 'Compare Date', titlePath: \._validFrom, css: 'col-md-2') ), HStack( TextView( title: 'Assets in use', mdText: '\(assetCount .% \'%d\')', mdFontId: 'assetCount', css: 'col-md-3' ), BarChart( title: 'Operating System', barPath: \.os, splitPath: \.status, statePath: \.os, valuePath: \._orgCode..count, query: Query( filters: ['_validFrom==\'\(date)\''], orderPaths: [\.os] ), emHeight: 16, css: 'col-md-3' ), PieChart( title: 'Status', piePath: \.status, statePath: \.status, valuePath: \._orgCode..count, query: Query( filters: ['_validFrom==\'\(date)\''], orderPaths: [\.status] ), emHeight: 16, css: 'col-md-3' ), PieChart( title: 'Environment', piePath: \.environment, statePath: \.environment, valuePath: \._orgCode..count, query: Query( filters: ['_validFrom==\'\(date)\''], orderPaths: [\.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: Query( paths: [\._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)")'], orderPaths: [\.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: