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: