Skip to content

Document Classes

In NodeActa system everything starts with a document class. Every record or a document in the system is an instance of a certain document class. Even apps, forms, reports, and charts, are all instances of a document class (SYS$APP).

To design a document class you have to do the following:

  • Assign a unique name to the class. Note that each class has Internal Name, Javascript Name and Display Name (Label).
  • Specify properties and options to the class.
  • Define class fields.
  • Define class indices.
  • Attach class to a storage.

Hint

Throughout the documentation, you will often see references to data class, document class or just class. A document class is generally a superset of a data class, meaning it's a data class with files (see 'Has Files' option in the Class Designer).

Class Designer

To see all available document classes in the system, go to System Managemen→Data Classes (Data Class Manager app).
And of course, to design a document class you will need a Class Designer. To start Class Designer, double click on a class in Data Class Manager app, or press Add Data Class button.

Hint

You can also use Add Data Class with AI button, if you want the system to use AI to automatically define class fields based on your description. Of course, AI is (still) not all powerful and this class will require additional fine tuning (especially with lookup definitions).

On the picture below we have shown the 'general' document class properties and options. The most of those are quite self-explanatory, but some will require clarification. When you select a property with your mouse, its description will appear at the bottom of the window.

designer-general

Class Properties

  • Base class: Allows you to have document class inheritance. For example, you can have a class 'CONTR' (Contract) and an inherited class 'ICONTR' (International Contract), which will inherit everyhting from the base 'CONTR' class and add a few of its own specific fields (see about 'Fileds' below).

  • Internal (DB) Name: The name we use to identify the class within the system. For example, 'INVC' is internal name and 'Invoice" is display Name. Internal (DB) Name is also the name of the database table system will create to persist your records (so, please keep it short and simple).
    Hint: This property is equivalent to myclassinstance.dataClass.classDatabaseName property in javascript.

  • Name: The class name displayed in UI. Maybe it's better to call it display Label.
    Hint: This property is equivalent to myclassinstance.dataClass.classLabel property in javascript.
    Warrning: When a class is already created, you can change its Name (Label), but not its Internal (DB) Name (remeber, there is a database strutcure behind using that name).

  • Javascript Name: The name used to identify your class in javacript code. Class 'Invoice' shown in the picture above, can be referenced in code like this:

    import {Invoice} from 'class:Invoice';// <= import {<Javascript Name>} from 'class:<Javascript Name>'
    ...
    var invoice = new Invoice();          // <= new <Javascript Name>()
    invoice.value = 339,99;
    invoice.currency = 'USD';
    ...
    invoice.save();
    

  • Category: This property helps you organize your classes. This comes helpfull when selecting your class in UI (classes will be grouped in categories, instead of being just one long list). Also, You can add your own categories, just by typing a new category name instead of selecting an existing one. If you add an icon to SYS$ICON class with the same name, your category will also have an icon displayed.

  • Validity: This property just allows you to keep the track of the work done on the class. If the class is valid and ready for use, or it has problems, or it should be deleted.

    Warning

    Never delete your class outright. Instead, mark it as 'To Delete.' Once you have accumulated enough classes for deletion, request your administrator to back up the database before proceeding with system cleanup.

  • Editor App: The name of the app system will use to edit records of this data class. In AttributesView or RecordsView, whenever you have a lookup to this class, you will have 'Edit Lookup' button. This button will run 'Editor App'. Even in your jsavascript code, whenever you want to edit some record, we suggest you invoking Editor App like this:

    let success = await myRecord.edit();        
    

  • Search App: The name of the app system will use to search records of this data class. In AttributesView or RecordsView, whenever you have Search lookup to this class, you will have 'Search Lookup' button. This button will run 'Search App'. Even in your jsavascript code, whenever you want to search for some record of this class, we suggest you invoking Search App like this:
    let selectedRecord = await MyClass.search(query);
    

Class Options

  • Has files (document/versioning support): Enable this option to turn your data class into a document class. This means, you will be able to attach and version files on your class object instance. If this option is NOT enabled, for example invoice.files.add(<some file path>) will throw an exception.
  • Compress files: Each file in this document class will be compressed before being sent to the server for archiving. However, even if this option is disabled, you can still enable compression for a specific file by setting file.isCompressed = true in your JavaScript code.
  • Encrypt files: Each file in this document class will be encrypted before being sent to the server for archiving. However, even if this option is disabled, you can still enable encritpion for a specific file by setting file.isEncrypted = true in your JavaScript code.
  • Hash-check record: If this option is enabled, the system will calculate hash property for each record after each change.

    Hint

    Record's hash validation is not done automatically. To verify the record hash against the current record values, you will have to call record.checkIntegrity() method. It will return true if record's values integrity is OK, or false if record values were tampered. Other option is use record's PropertiesWindow (call Context Menu→Properties in RecordsView for example), as it will show if the record integrity is violated or not.

    Warning

    Record's hash calculation depends on available record fields and their order, so if you reorder fields, rename, add new or delete existing, your record's hashes for that class will become invalid.

  • Hash-check file: If this option is enabled, the system will calculate hash property for each file on archiving. Unlike record's, file's hash checking is much more strict, and is done automatically. Whenever system detects mismatched file hashes, an exception is fired and you cannot access that file. With the files, if integrity is violated, everything stops.

  • Security: Records of this class will have record based security. That means you will be able to define ssecurity on each record. This record security will be added on class security itself and together will define effective security. Example of a class with security is SYS$APP.
  • Custom class: If this option is enabled, class will use provided select/insert/update/delete SQLs for record operations (see SQL tab in designer).
  • Memory class: If this option is enabled, class will keep all data in-memory, and will not ask server to query storage (database), and calling record.save() will not persist any data in any storage.
  • Access monitoring: If this option is enabled, system will keep the track if records are being 'read' by user. In RecordsView 'Unread' records will be shown as bold. If you select them, they will become 'Read' and will stop being bolded. To control access state of a record from javascript you can use record.markAsRead() and record.markAsUnRead() methods.

    Hint

    To display 'Un-Read' records in bold in RecordsView and automatically mark them as 'Read' when selected, set recordsView.options.userAccess = true.

    Hint

    The access monitoring period (default is 0) defines the number of days to track access. For example, if set to 365, a record modified over a year ago but not read will have its access status ignored and will appear as 'read' by default.

  • Log Attribute Changes: If this option is enabled, all class attribute (field value) changes will be logged in the specified LOG$XXX class. By default, the system comes with predefined LOG$DEFAULT class. If you anticipate frequent changes in a specific data class, consider creating for that class a dedicated 'LOG$XXX' class on a dedicated storage (database). To read your logs you can use System Management→Logs app.

    Hint

    To prevent log class to grow indefinitely, you could specify in server config file option MaxLogAge which specifies how many days log entries will be kept. This means that all log entires older that 'MaxLogAge' will be deleted. '0' means 'no limit'.

Class Fields

Class fields are the individual columns in a database table that define the structure of the data being stored. Each field represents a specific attribute of the data class and holds a particular type of data, such as text, numbers, dates, or boolean values.
For each feld you must configure the following properties:

  • Name: This is the name system uses to identify the field. Also, this is the name of a column in database table, so please keep it short.
  • Javascript Name: This is the name this field will be accessed by in javascript. For example invoice.myField.
  • Label: Used to represent the field in UI (RecordsView, AtributesView). Field's label can be localized with Localization app.
  • Kind (Data, Lookup, Fixed Lookup, Autogenerated, Calculated)
  • Type (Yes/No, Whole Number, Decimal, Currency, Floating-point Number, Date, Time, Date and Time, Fixed-length Text, Variable-length Text, Memo, Rich Text, Image, Binary)
  • Size and Scale for the types that require it

designer-fields

Optional field properties:

  • Caption field: At least one field must be designated as a caption field. All fields with the 'Caption field' option enabled will be combined to form a record's display label in the generic UI. In certain UI controls where selecting specific class fields for display is not possible, these 'Caption fields' will be used.
  • Must field: Fields marked with the Must field option must have a value before calling record.save(). In JavaScript, this option can be accessed through MyClass.myField.isOptional. Naturally, isOptional represents the negation of the Must field option.
  • Unique field: Fields marked as unique indicate that this class cannot contain multiple records with the same value for that field. Attempting to store such a record will raise an exception.
  • Default value: The initial value assigned to this field when a new instance of this class is created. For instance, if you declare var invoice = new Invoice(), all properties corresponding to fields with predefined default values will be automatically initialized. !!! hint For Date, Time, and DateTime field types, you can set NOW as the default value, which will assign the current date and time when the object instance is created.

  • Default Visibility: This setting determines whether the field will appear in RecordsView, AttributesView, and QueryParametersView, even without configuring the control's layout. The possible values are: Result, Attribute, and Search, corresponding to the RecordsView, AttributesView, and QueryParametersView controls, respectively.

  • Default Display Width: The width matching column in RecordsView will have by default (if RecordsView layout is not defined). Can be in pixels, in chars or in procentage. For Example: '100' => meaning 100 pixels, '20ch' => meaning 20 character width, '20%' => meaning 20% of entire RecordsView control width.
  • Default Display Height: The height matching row in AtributesView will have by default (if AtributesView layout is not defined). Can be in pixels, in chars or in procentage. For Example: 25 or '4ch' or '20%'.
  • Format Displaying: If you require a customized display of the field value in the UI, you can specify the appropriate format. For example, using 'YYYY-MM-DD' for a date field would present the date as '2024-03-19'. More about defining formats you can find here.
  • Format Editing: If you require custom formatting when editing the field value in the UI, you can define the desired format. For example, using 'YYYY-MM-DD' for a date field will force you to enter the date as '2024-03-19'. More about defining formats you can find here.
  • Hint: Description of the field that will appear as a tooltip when the mouse hovers over it in the AttributesView.

Lookup Fields

Lookups are a type of field that allows you to link (lookup) another document class to this class. Typically, this class will store only the key value from the lookup class (you can choose any field to act as the key field for the lookup). Additionally, you can define one or more display fields for the lookup, which will be automatically evaluated and populated without requiring an additional server request.
For example, the customer lookup has two display fields: Name and Address:

var invoice = new Invoice();
invoice.customer        => will be a lookup object of type Customer and this will trigger 
                           a server request to retrieve Customer record. 
invoice.customerName    => will be a lookup display field and it will not call the server. 
invoice.customerAddress => will be a lookup display field and it will not call the server. 

designer-fields

Lookup properites:

  • Type: You can have 2 different lookup types, Search and List.

    • List lookup will be displayed in UI with combobox filled with possible lookup values. List lookup should be used only when the number of possible lookup values is small (few dozens).
    • Search lookup will be displayed in UI with additional search button that will show Search Mask on click.

      Hint

      Serach mask shown for selecting search lookup value is actually lookup data class's Search App (see Class Properties).

    • Master: Special type of lookup is used to define Master-Slave relation with 2 data classes. If you specify a field to have master lookup type, this will turn this data class into a slave (detail) data class to selected lookup class (Selected Lookup class will be your 'master' in master-slave relationship).

  • Lookup Class: Data class that is the source of lookup.

  • By Reference: By default lookups are 'by reference'. This means that in this class only lookup class's key field value is storred. If you uncheck By Reference option, than all lookup Fields will have its own field in this class (lookup class values will be coppied).
  • Fields: Selected lookup class fields that will be displayed in this class.
  • Key Field: Mandatory lookup class field that is used to uniquely identify the record from that lookup class.
  • Caption Field: Main lookup field that will be displayed in lookup combobox in UI (if List lookup).
  • Sort Field: This field will be used to sort lookup values in combobox in UI (if List lookup). If this is Search lookup, this field will be used to sort rearch result.
  • Condition: You can filter the available lookup values based on this condition. Additionally, you can use values from the current record, making the lookup dependent on other record fields.

Class Indices

Just like with any database, you can use indices to tune performance of your database. If you create a class that will be ofter queried by certain fields, it's a good practice to create an index on that field, as database quering is much faster on indexed fields. Also, you can use indices to force unique values on multiple fields. This is similar like field's Unique Field property, just in the case you need a combination of multiple fields to be unique, you will create a unique index on those field (field's Unique Field property is not useful here, as it relates only to a single field).

Hint

Don't create too many indices per one document class, although they can improve querying performance, they will also decrease writing performance to this class database table.

Class Storages

After designing a class, to be able to use it to store the data, you have to attach it to a storage (database + archive). We need a database to store record/doocument attributes and we need an archive to store our files. Combining database and archive we make a logical entity named Storage.
To attach a class to a storage, use Add Working Storage button (see picutre above).

Hint

One class can have multiple storages. The first storage attached will serve as the primary storage. Additionally, you can have multiple non-primary working storages that function as backups for redundancy. This allows you to have multiple PCs to store identical data, ensuring that if one system fails, any remaining operational systems can take its place (not automatically, of course).
The primary storage is always used for querying data from the system and should be optimized for fast SELECT SQL query execution. In contrast, additional working storages are dedicated to writing operations and do not need to match the speed of the primary storage.

Hint

A class with checked option Memory class is an exception and does not require a storage. As the option name says, it's a class that is used to store structured data in memory and not in database/archive.

Security

If class has 'Security' option enabled (see Class Options), you will have the posibility to override existing class righs or even define new ones. In javascript code you can check if right is granted with record.checkRight(<right code>). You can also define additional rights or override existing ones (you will be able to rename the rights, but will not be able to change right codes).

designer-security