Creating a Json File
Content types are defined by using a JSON file. This guide shows you how to define a content type using a JSON document.
Preparations
- To be able to create a content type, you need a text editor - ideally with structuring features for the .json format like VS Code, Sublime Text or Notepad++
- To integrate the content type into a workbook, you need the iCL Designer.
- To upload the content type to the iCL Portal website, you need an account with administrator permissions.
JSON Basics
You can start a blank text file and save its data type to .json or edit an existing one and save it as a new .json file.
The JSON format is used to define the fields and features a content type has. Every time you add a new item of that content type, it is stored as a row in a data table, every field being a column of that table.
A content types JSON file defines several properties, some are optional, depending on the intended use or complexity. Further topics will explain the structure and options one by one.
JSON Structure
Every content type requires at least some basic parameters.
Some of them are optional and will get added automatically with a standard value after the upload to the iCL Portal like "icon", "version", "builtinTypeId" and "formTemplate"
This shows an easy example of a basic content type with two text and a number field.
{
"$type": "contentType",
"name": "ct_objects",
"displayName": "Content Type Name",
"titleFieldName": "obj_nr",
"titleFieldExpression": "<%obj_nr%> - <%obj_address%>"
"id": "73ee4c51-d99a-4596-9533-2bea4e0c65c5",
"builtinTypeId": 0,
"icon": "",
"version": 1,
"fields": [
{
"$type": "contentType",
"name": "obj_nr",
"displayName": "Object Number",
"isRequired": true
},
{
"$type": "contentType",
"name": "obj_address",
"displayName": "Object Address",
},
{
"$type": "contentType",
"type": "Number",
"name": "obj_floors",
"displayName": "Object Floors",
}
],
"relationships": [],
"formTemplate": {}
}
JSON Sections
There are different sections within the content type, some of them are optional or will be automatically generated.
In the fields bracket all existing content type fields will be defined. (Such as name, address, price, serial-number or whatever you need as a storable value)
Sometimes a content type is related to another one. For example, a content type elevator might belong to a building. These relations are defined in the relations brackets.
The formTemplate defines the form that is displayed to the user, when adding or editing items of that type. If omitted, a basic template will be generated automatically when uploading the content type to iCL Portal. Sometimes, however, you will want to modify the template. For example, if a dropdown selection is required for a certain field, you can define it in here.
When customizing the formTemplate, you do not have to define all fields. Just define the one field that you would like to change. When uploading the json file with the incomplete formTemplate to iCL Portal, it will notice that and fill in the missing fields for you.
Required JSON Attributes
These attributes are mandatory to make the content type work.
| Property | Parameter | Description |
|---|---|---|
"$type": | "contentType" | A property to define the json as a content type. |
"name": | "name_of_the_ct" | The unique name of the content type for the database - all lowercase, no spaces allowed (use _ instead). |
"displayName": | "Content Type Example" | The displayed name of the content type in the iCL Portal - Uppercase and spaces allowed. |
"id": | "12345678-90ab-cdef-1234-567890abcdef" | The unique identifier GUID (a 32 digit code) for the content type. It cannot exist twice on the iCL Portal, so it has to be unique for every content type used. |
"titleFieldName": | "most_unique_field" | When a content type lists all its data records (the so called content items), the titleFieldName defines the title shown for the data record. It uses the name of a field defined in the "fields": [] section and the referenced field has to be set to required. |
"fields": | [] | In the fields brackets, all the fields will be defined for the content type. It must have at least one required text field, which is connected with the titleFieldName parameter. |
The title field is important: Whenever you use a drop-down to select a content item, the iCL system needs to populate that dropdown with some meaningful text that allows the user to identify a particular item. For this, the titleFieldName is used, which is connected to a text field that needs to be required.
Another sample is when a related content item has to be shown in a data grid. For example, an elevator points to its building, so the data grid of elevator needs to display something in the "Building" column. This is another use case of the titleField
For each content type's field, a database column is created. By default, that column is not indexed.
If you want to be able to sort and filter by a field, you need to set the isIndexed property to true.
This will create an index for that column in the database, which will allow for faster sorting and filtering.
However, use this only where needed, as too many indexes can cause editing/updating items to become very slow.
Without index:
With index:
This behavior can be disabled using the following setting
Rate limit on queries of non-indexed fields
iCL Portal reminds users and API clients that a field they sort or filter by should be indexed:
the setting Rate limit on queries of non-indexed fields (ContentTypes.RateLimitForSearchesOnNonIndexedColumns, default 3) lets the same query on non-indexed fields through that many times and then refuses it once with an error.
Set it to 0 to switch the rate limit off.
Only the user who sent such a query sees the error. To learn about it as an administrator, enter one or more e-mail addresses in the setting Weekly report of rate limited requests: recipients (RateLimits.ReportRecipients) in the group Content Types of Settings > Settings.
Separate the addresses by semicolons or commas. To choose the language of an address's e-mail, add :en, :de or :fr to it; an address without a language gets the tenant's default language. For example:
admin@example.com:de; it@example.com:fr; boss@example.com
Saving the setting fails with a message that names the entry if a language is unknown (e.g. :es), an address is not valid, or an entry is empty (two separators in a row).
Set by the host administrator, the addresses apply to every tenant that does not set its own; leave the setting empty to send no report.
Once a week (by default on Mondays at 6:00 UTC, see the setting Schedule: weekly report of rate limited requests) the recipients get an e-mail with the queries refused in the last 7 days, one e-mail per language: for each content type and query the fields, how many requests were refused, by which users and when. The content types link to their lists in iCL Portal, and the e-mail links to this section.
The subject reads e.g. iCL Portal <tenant>: 11 requests refused by the rate limit in the last 7 days.
An index helps when a list is sorted by the field or searched with equals or starts with; a contains search cannot use an index.
Optional Content Type Properties
These properties will get a standard value, if not used, or just be ignored.
| Property | Parameter | Description |
|---|---|---|
"titleFieldExpression": | "ObjNr.: <%objectnumer%> <%fieldname%>" | To get a more detailed list of entries, you can extend the title of the content item here by creating a more complex combination of text and fields. |
"builtinTypeId": | 0 or 6 | This property sets the type of the content type. 0 is the standard value and adds the "isInspectable" quality to it. With a value of 6 it is defined as a defect content type, which needs a reference to a parent content type with the builtinTypeId 0. |
"icon": | "" | Reserved for future use - please leave empty. |
"version": | 1 | Reserved for future use - please leave empty. |
"relationships": | [] | Define relations to other content types here. If there is no reference to another content type needed, this can be left out. |
"formTemplate": | {} | If no specific dropdown field is required for the iCL Portal, this can be left out. |
"syncRules": | [] | Sync rules of a content type with filteredSynchronization enabled. If a field is mapped to ParentContentItemId, the downloaded definition also lists the built-in rule that synchronizes items along with their parent. Set "disabled": true on it to switch it off. Read more |
Fields
Within the fields brackets, all the fields of the content type will be defined. If not specified otherwise, a field is a simple text field and may look like this:
{
"$type": "contentField",
"name": "building_address",
"displayName": "Building Address"
}
Field Properties
The following properties define a content field:
| Property | Parameter | Mandatory | Description |
|---|---|---|---|
"$type": | "contentField" | x | The $type is always "contentField". |
"name": | "lowercase_and_underscore" | x | The name has to be unique and consists of lowercase letters. Use _ instead of spaces. |
"displayName": | "This is my Title" | x | The displayName is used as the title of the entry. Uppercase and Space allowed. |
"type": | "Text" | The type (without the $) defines the datatype of the field. If unused, it is set as a text field by default. Other parameters are the following: | |
"Number" | Turns the field into a number field. | ||
"Date" | A Date format to store date values (including time) | ||
"Time" | Allows you to save times (hours:minutes) | ||
"ContentItem" | The field is able to store a reference to another content type. | ||
"FileEntry" | File entry fields are able to store images. | ||
"Plan" | |||
"isRequired": | true or false | By default, fields are not required to have a value - so you only need to set this if you want the field to be mandatory. | |
"isIndexed": | true or false | The default value is set to false. If set to true, users can search and sort - e.g. in the datagrid - using those fields. Use this sparingly, though, as too many indexes can cause editing/updating items to become very slow. | |
"builtInField": | "ParentContentItemId" | A content type with the "builtinTypeId": 6 requires a parent content type to be defined. The parent content type is the one that the defect belongs to. It is stored in a content field of type ContentItem and needs to specify this property. | |
"ExternalId" | A field with this parameter is considered as the reference field, where every entry has to be unique. | ||
"Status" | The iCL System treats defect content types in a special way: In certain screens, it will allow to sort and filter them by their status. For this to work, however, you need to map a content field of type Number - representing the state of the defect - to the builtInField: Status. |
Relationships
Relationships are connections to other content types. The parent content type must have "builtinTypeId": 0.
Every content type with a "builtinTypeId": 6 needs a reference to its 'parent' content type, which is established in two ways: a field of "type": "contentItem" and a "relationships": {} section which creates a references to that content item field.
Reference Field
If you build a relation to another content type in the relationships area, you also need a field with the "type": "ContentItem" property to store it's reference.
Use a name and title for this field, which makes it clear that it is a reference. Like "obj_id" as name for a stored reference id of a content type called "Object". The _id suffix helps identifying such reference fields, if you stick to that standard.
The field definition may look like this:
{
"$type": "contentField",
"type": "ContentItem",
"name": "obj_id",
"displayName": "Object ID"
}
If the current content type is a defect ("builtinTypeId": 6) type, you additionally need the "builtinField": "ParentContentItemId" property for that field:
{
"$type": "contentField",
"type": "ContentItem",
"name": "obj_id",
"displayName": "Object ID"
"builtinField": "ParentContentItemId"
}
You can set this builtinField parameter in only one ContentItem field.
Relationships Section
All relations to another content types will be defined in the relationships section, which is structured as follows:
"relationships": [
{
"$type": "contentRelationship",
"name": "obj_ref",
"displayName": "Object Ref",
"foreignKeyField": "obj_id",
"targetContentType": {
"$type": "contentTypeRef",
"id": "21429549-7b35-4cb1-bd6a-ac4f5ea9fbb8",
"version": 1
}
}
]
A reference needs to be defined with a name and displayName as every other part of the content type definition.
Beside that, it has to reference to a field of "type:" "ContentItem" in the "fields": [] section and additionally it has to know the unique id (Guid) of the content type, to which this reference is pointing to. You will find the GUID in the "id": parameter of that other JSON file.
| Property | Parameter | Description |
|---|---|---|
"$type": | "contentRelationship" | This never changes. |
"name" | "obj_ref" | The name of this relation object. Best practice: use the name of the field, where the content type will be stored at and attach a _ref to it. |
"displayName" | "Object Ref" | The title of this relationship - since it isn't displayed anywhere, it doesn't matter much. |
"foreinKeyField" | "obj_id" | The name of the field, where the reference will be stored (it has the "type": "ContentItem" property). |
"targetContentType": {} | $type: "contentTypeRef" | This never changes. |
"id:" "12345678-abcd-4321-9876543210ab" | The GUID of the content type, to which the reference is pointing at. | |
"version": 1 | This never changes. |
You can add more than one reference by opening a new {} section within the "relationships": [] brackets, seperated with a comma like this:
"relationships": [
{
"$type": "contentRelationship",
"name": "obj_ref",
"displayName": "Object Ref",
"foreignKeyField": "obj_id",
"targetContentType": {
"$type": "contentTypeRef",
"id": "12345678-abcd-4321-9876543210ab",
"version": 1
}
},
{
"$type": "contentRelationship",
"name": "items_ref",
"displayName": "Items Ref",
"foreignKeyField": "items_id",
"targetContentType": {
"$type": "contentTypeRef",
"id": "87654321-dcba-4321-ba0123456789",
"version": 1
}
}
]