> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cognite.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Configure Maintain

> Learn how to configure Cognite Maintain, including data modeling spaces, access control, data ingestion, and feature configurations.

<Warning>
  The features described in this section are in [public preview](/cdf/product_feature_status#public-preview) and may change.
</Warning>

## Before you start

Make sure you have the following:

* A project registered in the [CDF application](https://fusion.cognite.com).
* [The CDF API and the CDF application registered in Microsoft Entra ID](/cdf/access/entra/guides/configure_cdf_azure_oidc) and [Microsoft Entra ID and CDF groups set up to control access to CDF data](/cdf/access/entra/guides/create_groups_oidc/).
* Assets in the CDF project populated in the [`CogniteAsset` concept](/cdf/dm/dm_reference/dm_core_data_model#asset).
* [URLs](/cdf/admin/allowlist/) in your allowlist.

## Create data modeling spaces

Maintain stores asset data in [data models](/cdf/dm/). You need to create at least 3 spaces to store your data and data models.

| Space name                     | Description                                                                                                      |
| ------------------------------ | ---------------------------------------------------------------------------------------------------------------- |
| `cdf_apps_shared`              | This space holds user data, such as user profiles, and application configuration.                                |
| `yourRootLocation_source_data` | This space holds source data (data coming from a customer source system, such as SAP) for a particular location. |
| `yourRootLocation_app_data`    | This space holds data coming from Maintain (from plans and layouts) for a particular location.                   |

<Tip>
  Create new `yourRootLocation_source_data` and `yourRootLocation_app_data` spaces for each root location you have if you want to implement access control per location.
</Tip>

You can create spaces in the following ways:

<Tabs>
  <Tab title="Python SDK">
    You can create the spaces using [Cognite Python SDK](https://cognite-sdk-python.readthedocs-hosted.com/en/latest/index.html). Use the following Python code and replace `yourRootLocation` with your root location/asset name in `yourRootLocation_source_data`, `yourRootLocation_app_data`.

    ```python theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
    from cognite.client.data_classes.data_modeling import SpaceApply

    # List of spaces to create
    spaces_to_create = ["yourRootLocation_source_data", "yourRootLocation_app_data", "cdf_apps_shared"]

    # Apply spaces
    for space_name in spaces_to_create:
     client.data_modeling.spaces.apply(SpaceApply(space=space_name))
    ```
  </Tab>

  <Tab title="API">
    Create the spaces using the [API endpoint](/api-reference/concepts/20230101/spaces), and replace `yourRootLocation` with your root location/asset name in `yourRootLocation_source_data`, `yourRootLocation_app_data`.

    <Note>
      The values for the `space` and `name` attributes must be identical. The `space` attribute value is also the space identifier.
    </Note>
  </Tab>
</Tabs>

## Set up access

You can use your existing identity provider (IdP) framework to manage access to Maintain and choose admin users. Maintain supports Microsoft Entra ID, Microsoft's cloud-based identity and access management service. By creating groups, you can assign different sets of capabilities to users and give each group different access rights.

### Create an admin group

<Tip>
  If you already have an admin group with the same capabilities, you can reuse that group and skip this step.
</Tip>

Create a group of users who can configure the Maintain application across all [locations](/cdf/locations/index?search=location). See also how to [configure locations](#configure-locations).

<Steps>
  <Step title="Navigate to Manage access">
    Go to [***CDF***](https://fusion.cognite.com) > ***Manage*** > ***Manage access***.
  </Step>

  <Step title="Create a group">
    Create a group and name it, for example, `industrial_tools_admin`.
  </Step>

  <Step title="Assign capabilities">
    Assign `read` and `write` access to all capabilities with the scope `All`, or assign the minimum set of capabilities.

    | Capability type      | Action                         | Scope             | Description                                               |
    | -------------------- | ------------------------------ | ----------------- | --------------------------------------------------------- |
    | Groups               | `groups: read`, `groups: list` | All               | For Maintain administrators to grant access to users.     |
    | Data models          | `dataModel: read`              | All               | View data models.                                         |
    | Data model instances | `dataModelInstance:read`       | All               | Access data organized in data models.                     |
    | Data model instances | `dataModelInstance:write`      | `cdf_apps_shared` | Access and edit data organized in data models and spaces. |
  </Step>
</Steps>

### Create user groups

Create groups of users who can view activities, create plans and campaigns, and work with different layouts. You can create several groups with different capabilities. For example:

| Group name       | Description                                              |
| ---------------- | -------------------------------------------------------- |
| `maintain_plans` | Users in this group can view and edit plans and layouts. |

Assign the following group capabilities:

| Capability type      | Action                         | Scope                                                                                                                                                                            | Description                                               |
| -------------------- | ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- |
| Groups               | `groups: read`, `groups: list` | All                                                                                                                                                                              | View user groups.                                         |
| Data models          | `dataModel: read`              | `cdf_cdm`, `cdf_idm`, `cdf_maintain`, `cdf_apps_shared`, `idm_customer_datamodel_space` - the space where you extend the views                                                   | View and analyze the data created in Maintain.            |
| Data model instances | `dataModelInstance:read`       | `cdf_apps_shared`, `location_app_data_space`, `location_source_data_space` - a list of spaces to read the data from. Add all spaces you want to read the data from to the scope. | View and analyze the data created in Maintain.            |
| Data model instances | `dataModelInstance:write`      | `cdf_apps_shared`                                                                                                                                                                | Access and edit data organized in data models and spaces. |

## Populate data models

All data for Maintain is stored within data models, with a few exceptions. Generally, most tabular data exists in [CDF RAW](/api-reference/concepts/20230101/raw). Once the data is in RAW, you can use transformations to change this data into one of the following data models, depending on the view.

### Core data models

Maintain requires specific data models to function. Missing models will cause features to fail silently or prevent the app from loading entirely. The following concepts are part of Cognite's core data model and must be available in your CDF project:

| Model                      | Space      | Version | Purpose                | Required For                            |
| -------------------------- | ---------- | ------- | ---------------------- | --------------------------------------- |
| `CogniteAsset`             | `cdf_core` | `v1`    | Base asset hierarchy   | All asset-related features              |
| `CogniteFile`              | `cdf_core` | `v1`    | File management        | All document features                   |
| `CogniteDiagramAnnotation` | `cdf_cdm`  | `v1`    | Asset-to-diagram links | P\&ID annotations and contextualization |
| `CogniteCADRevision`       | `cdf_cdm`  | `v1`    | 3D model revisions     | 3D contextualization                    |

### Common data model issues

If you encounter issues with your data models, see the table for causes and fixes.

| Issue                    | Cause                                   | Solution                                                                    |
| ------------------------ | --------------------------------------- | --------------------------------------------------------------------------- |
| Annotations don't appear | Missing `CogniteDiagramAnnotation` view | Verify the view exists in the `cdf_cdm` space                               |
| File won't open          | Wrong `mimeType`                        | Match `mimeType` to the actual file format (for example, `application/pdf`) |
| Can't find in UI         | Missing `documentCategory: "PID"`       | Add category to the `ExtendedFile` node                                     |
| Multi-page PDF broken    | Wrong `startNodePageNumber`             | Set the correct page number (1-indexed)                                     |

### Data entities to populate

<Tip>
  Complete most of the data entities to use the application effectively. Ingest the data entities in the order they appear in the table. Once you ingest `Assets` and `Maintenance orders`, open the application to check that this data appears correctly.
</Tip>

| Data entity                          | View                              |
| ------------------------------------ | --------------------------------- |
| Asset                                | cdf\_cdm.Asset                    |
| Maintenance orders (work orders)     | cdf\_idm.CogniteMaintenanceOrder  |
| Operations                           | cdf\_idm.Operations               |
| Files (P\&IDs)                       | cdf\_cdm.File                     |
| Annotations (file contextualization) | cdf\_cdm.DiagramAnnotation (edge) |
| 3D                                   | Ingested through 3D APIs          |

<Tip>
  Use the existing [3D APIs](/api-reference/concepts/20230101/3d-models) to ingest 3D data even though it's stored in data models. Learn more about [uploading 3D models](/cdf/3d/guides/3dmodels_upload) and [linking assets to 3D objects](/cdf/3d/guides/3dmodels_contextualize).
</Tip>

You can also use the [Cognite Toolkit](/cdf/deploy/cdf_toolkit/) to populate data models. Learn more about [using the Cognite Toolkit with Maintain](#use-the-cognite-toolkit).

### Maintain-managed data entities

The following data entities are created automatically by Maintain when users create plans, layouts, and annotate diagrams. You don't need to populate instances manually, but you must ensure the data model views exist and the app data space is properly configured.

| Data entity | View                                  | Trigger                        |
| ----------- | ------------------------------------- | ------------------------------ |
| Plan        | `APM_Plan` or `MaintainPlan`          | Users create plans in Maintain |
| Layout      | `Maintain_Layout` or `MaintainLayout` | Users save custom layouts      |
| Canvas      | `APM_Canvas` or `MaintainCanvas`      | Users annotate diagrams        |

<Note>
  Maintain stores plan, layout, and canvas **instances** in your configured `appDataInstanceSpace` (for example, `yourLocation_app_data`). The **view definitions** come from the `cdf_maintain` space or your custom data model space if you've extended them.
</Note>

<Tip>
  **Important for IDM/CDM deployments**: Your `appDataInstanceSpace` must include the **APM\_AppData data model** (or equivalent system data model) containing views such as `APM_Plan`, `APM_User`, `Maintain_Layout`, `APM_Canvas`, `APM_Comment`, `APM_Marker`, and `Maintain_FileGridZoneAnnotation`. These views are required **regardless of whether Maintain runs in APM or IDM/CDM mode**. The deployment mode only affects source data configuration (activities, operations, assets), not the app data space structure.
</Tip>

## Use the Cognite Toolkit

The [Cognite Toolkit](/cdf/deploy/cdf_toolkit/) is a command-line tool for deploying Maintain configurations to CDF. Understanding its commands and flags is essential for efficient development and troubleshooting.

## Configure Maintain

Once you have data ingested, you can configure Maintain to use it.

<Steps>
  <Step title="Sign in to Maintain">
    Sign in to [Maintain](https://maintain.cogniteapp.com) with your organization ID.
  </Step>

  <Step title="Select spaces">
    Select the spaces for the source data (`yourRootLocation_source_data`) and for the application data (`yourRootLocation_app_data`).
  </Step>
</Steps>

A basic configuration named *Default* is set up. The configuration uses JSON and allows flexibility in how you view Maintain. You can see examples of [Field Configuration](#field-configuration) and [Feature Configuration](#feature-configuration).

### Extend data models

[Views](/cdf/dm/dm_concepts/dm_containers_views_datamodels#views) contain a group of properties that you can change for specific cases. By default, Maintain uses the Cognite process industries data model that extends the core data model to meet the requirements for the process industries. You can customize entity definitions or views, such as `CogniteAsset` and `CogniteMaintenanceOrder`, by adding properties that are specific to your operations. For example, to extend the `CogniteMaintenanceOrder` property, you can create a new view and add the `Cost` field to this property.

<Tip>
  If you're using the Cognite Toolkit to create custom views for activities or operations, follow the standard view structure with Container, View, and Node YAML files. See the [Cognite Toolkit documentation](/cdf/deploy/cdf_toolkit/) for examples and templates.
</Tip>

In Maintain, you can filter on entities such as activities and assets, using views defined in the `cdf_idm` (Process industries data model), `cdf_cdm` (Core data model) spaces, or the space with your custom views.

To set up how you want to query CDF data modeling:

<Steps>
  <Step title="Sign in to Maintain">
    Sign in to [Maintain](https://maintain.cogniteapp.com) with your organization ID.
  </Step>

  <Step title="Open configuration">
    Under Cognite Maintain, select the dropdown > ***yourConfig*** > <Icon icon="pencil" /> (edit).
  </Step>

  <Step title="View mappings">
    In ***Feature Configuration***, you'll see your view mappings.

    ```json theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
    "viewMappings": {
        "asset": {
          "type": "view",
          "space": "cdf_cdm",
          "version": "v1",
          "externalId": "CogniteAsset"
        },
        "activity": {
          "type": "view",
          "space": "cdf_idm",
          "version": "v1",
          "externalId": "CogniteMaintenanceOrder"
        },
         "operation": {
          "type": "view",
          "space": "cdf_idm",
          "version": "v1",
          "externalId": "CogniteOperation"
        },
        "notification": {
          "type": "view",
          "space": "cdf_idm",
          "version": "v1",
          "externalId": "CogniteNotification"
        }
    }

    ```
  </Step>

  <Step title="Configure spaces">
    For each property, keep the default space or select the space where you created custom views.
  </Step>

  <Step title="Save changes">
    Select **Apply** to save the changes.
  </Step>
</Steps>

### Field configuration

<Tip>
  The Maintain Field and Feature configurations are currently based on RAW JSON. Copy the configuration into a text editor, edit it, and then paste it back into the configuration modal.
</Tip>

Field Configuration lets you choose which fields to show, how they look in the user interface, and how you can use the fields. The Field Configuration is a JSON object that contains one key-value pair for each field in the activity view type that should appear in Maintain. The key should be the name of the field in the activity view type, while the value is a JSON object containing the configuration of that field in Maintain.

This example shows two configured fields:

```json theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
{
    "title": {
        "alias": "Activity title",
        "displayInTable": 1
    },
    "status": {
        "alias": "Status",
        "displayInTable": 2
    }
}
```

In the example, Maintain displays two fields in the Activity table, with the “title“ field renamed to “Activity title“ and “status“ renamed to “Status“. Ensure the title appears before the status.

You can further configure individual fields by adding entries to Field Configuration. The following table lists the basic configuration properties:

| Config key                       | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                            | Type                                          | Default, if not set                                   |
| -------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------- | ----------------------------------------------------- |
| `additionalTableField`           | Define whether this field should display an additional accessory field under it in the Activity table. The value is the name of the field to show in the Activity table.                                                                                                                                                                                                                                                                                                               | string                                        | null                                                  |
| `alias`                          | A string or an object containing a clear field name in different languages.                                                                                                                                                                                                                                                                                                                                                                                                            | string                                        | Same value as the name of the field in the data model |
| `allowFilteringByMultipleValues` | On `fieldSubtype`: "FREETEXT" fields only; enables filtering by multiple values separated by comma.                                                                                                                                                                                                                                                                                                                                                                                    | boolean                                       | false                                                 |
| `approximateDataSize`            | Define how much space the field will occupy in the Activity table.                                                                                                                                                                                                                                                                                                                                                                                                                     | string: 'tiny', 'small', 'medium', or 'large' | 'medium'                                              |
| `blacklisted`                    | Define whether this field should be completely excluded from being displayed in the application.                                                                                                                                                                                                                                                                                                                                                                                       | boolean                                       | false                                                 |
| `colorCoding`                    | Configures this field to have color coding based on the value. See [Color coding configuration](#color-coding-of-fields).                                                                                                                                                                                                                                                                                                                                                              | object                                        | null                                                  |
| `colorCodingInGantt`             | If "colorCoding" is set, enable coloring Gantt for this field.                                                                                                                                                                                                                                                                                                                                                                                                                         | boolean                                       | false                                                 |
| `colorCodingInTable`             | If "colorCoding" is set, use coloring on this field in the table.                                                                                                                                                                                                                                                                                                                                                                                                                      | boolean                                       | false                                                 |
| `dateFormat`                     | Set a custom date format for date fields. See [possible formats](https://day.js.org/docs/en/display/format).                                                                                                                                                                                                                                                                                                                                                                           | string                                        | null                                                  |
| `decimalPoints`                  | Enter the number of decimal points to show if this is a number field. For example, if the value is "5.55555" and `decimalPoints` is set to 2, the value to appear in the application will be "5.56".                                                                                                                                                                                                                                                                                   | number                                        | null                                                  |
| `displayInColumnsSidebar`        | Define whether this field should be displayed in the columns sidebar at the top level. You can group all fields under "Show all attributes", but these are displayed first.                                                                                                                                                                                                                                                                                                            | boolean                                       | false                                                 |
| `displayInFilterMenu`            | Define whether this field should be displayed by default in the filtering menu sidebar. Note that the user can add fields manually later, but this should be true for "common" fields to filter on.                                                                                                                                                                                                                                                                                    | boolean                                       | false                                                 |
| `displayInGantt`                 | Define whether the value of this field should be displayed under the activity bar in the Gantt lens.                                                                                                                                                                                                                                                                                                                                                                                   | boolean                                       | false                                                 |
| `displayInGroupDropdown`         | Define whether this field should be displayed in the group dropdown menu at the top level. You can group all fields under "Show all attributes", but these are displayed first.                                                                                                                                                                                                                                                                                                        | boolean                                       | false                                                 |
| `displayInSmallActivityCardView` | Define the order in which this field appears in the small activity card view. If not provided, the field isn't displayed in the small activity card.                                                                                                                                                                                                                                                                                                                                   | number                                        | null                                                  |
| `displayInSortDropdown`          | Define whether this field should be displayed in the Sort dropdown.                                                                                                                                                                                                                                                                                                                                                                                                                    | boolean                                       | false                                                 |
| `displayInTable`                 | Define whether this field should be displayed in the table by default. The number provided defines the order in which the field will appear. If not provided, the field isn't displayed in the Activity table by default.                                                                                                                                                                                                                                                              | number                                        | null                                                  |
| `enableHourSelection`            | Enable hour selection in the date picker for date fields.                                                                                                                                                                                                                                                                                                                                                                                                                              | boolean                                       | false                                                 |
| `enableInCsvImport`              | Define whether this field should be included in CSV and Excel exports. Only fields with this field set to `true` will be exported.                                                                                                                                                                                                                                                                                                                                                     | boolean                                       | false                                                 |
| `fieldSubtype`                   | Define the field's subtype. This is used to define how filtering works in this field. Setting to "OPTION" shows a dropdown list of all existing values. Setting to "FREETEXT" will let the user filter the field by a simple text string. Use “FREETEXT” for any field where each value is unique, such as ID-type fields. Set it to "URL" to show a link with either custom display text or the raw URL. See [Configure fieldSubtype URL option](#configure-fieldsubtype-url-option). | string: 'FREETEXT', 'OPTION', 'URL'.          | 'OPTION'                                              |
| `postfix`                        | Enter the postfix to show next to the field value. For example, if the postfix is set to `$` and the field value for an activity is `5`, the text to appear in the application will be `5$`.                                                                                                                                                                                                                                                                                           | string                                        | null                                                  |
| `prefix`                         | Enter the prefix to show next to the field value. For example, if the prefix is set to `$` and the field value for an activity is `5`, the text to appear in the application will be `$5`.                                                                                                                                                                                                                                                                                             | string                                        | null                                                  |
| `urlDisplayText`                 | On `"fieldSubtype"`: `"URL"` fields only; the field is optional. If provided, the table cell displays the defined text. If not provided, the default display text is `"Link"`.                                                                                                                                                                                                                                                                                                         | string                                        | `"Link"`                                              |

#### Configure fieldSubtype URL option

You can define a field with `"fieldSubtype": "URL"`. The underlying value of the field must be a valid URL. Optionally, you can specify `"urlDisplayText"` which determines the text shown in the table. If provided, the table cell displays the defined text. If not provided, the default display text is `"Link"`.

If all conditions are met, the link will:

* Render in the table in blue and be clickable.
* Open in a new browser tab pointing to the given URL.

This example shows how to configure the URL link for the `sapLink` field:

```json theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
{
  "sapLink": {
    "alias": "SAP Link",
    "readOnly": true,
    "fieldSubtype": "URL",
    "urlDisplayText": "Open in SAP"
  }
}
```

#### Color coding of fields

You can configure color coding for the Gantt chart and the Activity table. If you've configured color coding for the specific fields, Maintain lets you color-code the Gantt bars. The color coding is defined by providing a specific color for each value of the field. By default, all values without explicit color coding are gray. You can set the color coding in the Field Configuration.

This example shows how to configure color coding for the `materialStatus` field:

```json theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
{
...
  "materialStatus": {
    ...
    "colorCoding": {
      "OK": {
        "background": "rgba(0, 100, 0, 1)",
        "color": "rgba(0, 255, 0, 1)"
      },
      "MISSING": {
        "background": "rgba(100, 0, 0, 1)",
        "color": "rgba(255, 0, 0, 1)"
      }
    },
    "colorCodingInGantt": true,
    "colorCodingInTable": true
  }
}
```

If the field value is `"OK"`, it will be colored green; if it's `"MISSING"`, it will be colored red. This field will be colored both in the table and the Gantt chart.

### Operation field configuration

Operation field configuration lets you customize which fields appear on operation rows in the activity card, their display order, and their labels. Without this configuration, Maintain shows a fixed set of fields (`type`, `title`, `mainResource`, and `personHours`) in a predetermined order.

When the `MAINTAIN_operation_field_config` toggle is [enabled](#enable-operation-field-configuration) for your environment, the **Operation field configuration** section appears in the app config modal.

The following table shows how the toggle state and configuration affect the UI:

| Toggle state | Config present   | Result                                                                                     |
| ------------ | ---------------- | ------------------------------------------------------------------------------------------ |
| OFF          | Any              | Default layout: shows `type`, `title`, `mainResource`, and `personHours` in a fixed order. |
| ON           | Empty or missing | Default layout: shows `type`, `title`, `mainResource`, and `personHours` in a fixed order. |
| ON           | Has fields       | Shows only fields with `displayInTable` set to `true`, sorted by `orderInOperationRow`.    |

<Tip>
  The Maintain Field and Feature configurations are currently based on RAW JSON. Copy the configuration into a text editor, edit it, and then paste it back into the configuration modal.
</Tip>

The configuration is a JSON object where each key is a field name from the operation view and the value is a configuration object. This example configures three fields to display in Maintain (Operation name, Type, and Discipline):

```json theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
{
  "title": {
    "alias": "Operation name",
    "displayInTable": true,
    "orderInOperationRow": 1
  },
  "type": {
    "alias": "Type",
    "displayInTable": true,
    "orderInOperationRow": 2
  },
  "mainResource": {
    "alias": "Discipline",
    "displayInTable": true,
    "orderInOperationRow": 3
  }
}
```

The following table lists the available configuration properties:

| Config key            | Description                                                                     | Type    | Default, if not set                      |
| --------------------- | ------------------------------------------------------------------------------- | ------- | ---------------------------------------- |
| `alias`               | A display name for the field. Shown in tooltips as "alias: value".              | string  | Same as the field name in the data model |
| `displayInTable`      | Whether the field is visible on the operation row.                              | boolean | `false`                                  |
| `orderInOperationRow` | The sort position of the field on the operation row. Lower values appear first. | number  | `null`                                   |

#### Field types

Operation fields fall into two categories: core fields with specialized rendering and generic fields rendered as plain text.

**Core fields** have specialized rendering:

| Field name     | Renders as            | Notes                                    |
| -------------- | --------------------- | ---------------------------------------- |
| `type`         | Operation type badge  | For example, "Exe", "VAL"                |
| `title`        | Operation title text  | Truncated with ellipsis at 65% max-width |
| `mainResource` | Resource header text  | Combines resource name and count         |
| `personHours`  | Hours with "h" suffix | For example, "2h"                        |

**Generic fields** include any other operation property, such as `systemStatus`, `numberOfMainResource`, `sourceId`, `startTime`, or `description`. Generic fields support string, number, and date values. Date values are formatted using locale settings. Fields with `null`, `undefined`, or object values are skipped.

#### Sorting and display

Maintain sorts operation fields using these rules:

* Fields with `orderInOperationRow` defined are sorted in ascending order (lower values first).
* Fields with an order value appear before fields without one.
* Fields without an order value are sorted alphabetically by field name.

There is no hard limit on the number of fields you can configure. All fields with `displayInTable` set to `true` are rendered inline in a single row. Long values on `title` and generic fields are capped at 65% max-width with ellipsis truncation.

#### Tooltip behavior

When you configure an `alias`, tooltips show the alias followed by the value, for example, "Discipline: MECH". Without an alias, core fields show their default tooltip, and generic fields show the raw value.

#### Enable operation field configuration

To enable operation field configuration for a new environment, complete the following steps:

<Steps>
  <Step title="Update the data model view">
    <Tabs>
      <Tab title="CDF_AppLocationConfig (new)">
        If your environment uses the `CDF_AppLocationConfig` view, no changes are needed. The `operationFieldConfiguration` field is already included.
      </Tab>

      <Tab title="APM_Config (legacy)">
        If your environment uses the older `APM_Config` view:

        1. Add `operationFieldConfiguration: JSONObject` to the `APM_Config` data model.
        2. Publish as a new view version (for example, version 3).
        3. Update the `configurationSchemaVersion` for the project to point to the new view version.
        4. Deploy the code change.
      </Tab>
    </Tabs>
  </Step>

  <Step title="Enable the feature toggle">
    Enable the `MAINTAIN_operation_field_config` toggle for the target environment and project.
  </Step>

  <Step title="Configure fields">
    1. Open the app config modal in Maintain.

    2. In the **Field operation configuration** textarea, enter the JSON configuration. For example:

       ```json theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
       {
         "type": { "alias": "Type", "displayInTable": true, "orderInOperationRow": 1 },
         "title": { "alias": "Title", "displayInTable": true, "orderInOperationRow": 2 },
         "systemStatus": { "alias": "System Status", "displayInTable": true, "orderInOperationRow": 3 },
         "mainResource": { "alias": "Resource", "displayInTable": true, "orderInOperationRow": 4 },
         "personHours": { "alias": "Person Hours", "displayInTable": true, "orderInOperationRow": 5 }
       }
       ```

    3. Select **Apply**.
  </Step>

  <Step title="Validate">
    1. Verify that operation rows display fields in the configured order with aliases in tooltips.
    2. Reopen the config modal and confirm that the configuration persists.
  </Step>
</Steps>

#### Disable operation field configuration

To disable operation field configuration, turn off the `MAINTAIN_operation_field_config` toggle. The UI immediately falls back to the default layout. No data migration or cleanup is needed as Maintain ignores the stored configuration when the toggle is off.

### Feature configuration

You can configure optional features in Maintain, such as time and date, landing page, and language.

#### Landing page configuration

You can configure the landing page to show the user's name. By default, the page shows a welcome message without a name.

The name of a user depends on the customer's IdP, so the way to format the name is different for each customer. If you set the `displayNameRegex` property in Feature Configuration to a regular expression with a capture group for "name", Maintain shows only the matching substring in the header. For example, if the customer has a "last\_name, first\_name" format in their IdP, the following configuration can be used to display "Welcome, first\_name":

```json theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
displayNameRegex: ".*, (?<name>.*)"
```

The format of the regular expression must follow the [JS standard](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions/Cheatsheet).

#### Language configuration

Maintain supports multiple languages. When signing in for the first time, you can see a list of available languages. If you need certain languages to be available, set the `availableLanguages` property in Feature Configuration.

This example shows how to set the English and German languages:

```json theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
"availableLanguages": ["en", "de"]
```

To get a full list of available languages, contact Cognite customer support.

#### Customer-specific language configuration

By default, Maintain supports localization of native application strings only. Custom strings aren't translated automatically and there are features that require manual translation:

* Naming of fields in the data model. See [Field Configuration](#field-configuration) > `alias`.

#### Time and date configuration

To configure how dates are formatted globally in Maintain, set the following keys under `timezoneConfiguration` in Feature Configuration:

| Config key       | Description                                                                                                                                                                                                                                              | Type   | Default if not set |
| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | ------------------ |
| `startOfWeek`    | Set the starting day of the week. Possible values: `0` to start the week on Sunday; `1` to start the week on Monday. This affects date picker components in the application and also which day is the first day in the Gantt header on week granularity. | string | 1                  |
| `dateFormat`     | Set the global date format for dates. See [possible formats](https://day.js.org/docs/en/display/format).                                                                                                                                                 | string | “DD/MM/YYYY“       |
| `dateTimeFormat` | Set the global date format for date and time, for example, where dates and time of the day are shown together. See [possible formats](https://day.js.org/docs/en/display/format).                                                                        | string | “DD/MM/YYYY HH:mm“ |

#### Gantt

The Gantt lens is added by default. To remove the Gantt lens, set `"disabled"` to `true` in Feature Configuration:

```json theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
"ganttConfiguration": { "disabled": true }
```

#### Operations

To add operations, set `"enabled"` to `true` in Feature Configuration:

```json theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
"subactivitiesConfiguration": { "enabled": true }
```

#### 3D and digital twin

The 3D feature is added by default. To remove the functionality, set `"disabled"` to `true` in Feature Configuration:

```json theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
"threeDConfiguration": { "enabled": false }
```

<Tip>
  Learn how to [upload 3D models](/cdf/3d/guides/3dmodels_upload) and [link assets to 3D objects](/cdf/3d/guides/3dmodels_contextualize) for improved asset discoverability and navigation in Maintain.
</Tip>

##### Basic configuration

The 3D configuration requires configuring the 3D models (locations). You can do this in Maintain > ***your.Config*** > ***Root Location Configuration***. Make an entry in this JSON object for each location, for example, a 3D model to visualize.

Each entry needs to have the following properties:

| Entry        | Description                                                                                    |
| ------------ | ---------------------------------------------------------------------------------------------- |
| `label`      | The display name of the location that appears in the application.                              |
| `value`      | The unique identifier of the location; can be anything as long as it's unique for the project. |
| `modelId`    | The ID of the CDF 3D model for this location.                                                  |
| `revisionId` | The revision ID of the CDF 3D model.                                                           |

This example shows how to configure a project that has two locations, Site A and Site B:

```json theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
{
  "locations": [
    {
      "label": "Site A",
      "value": "SITE_A",
      "modelId": 1234,
      "revisionId": 5678
    },
    {
      "label": "Site B",
      "value": "SITE_B",
      "modelId": 9012,
      "revisionId": 3456
    }
  ]
}
```

<Tip>
  You can find the `modelId` and `revisionId` in CDF by navigating to your 3D model. Use the [3D APIs](/api-reference/concepts/20230101/3d-models) to retrieve model and revision IDs programmatically.
</Tip>

If all criteria are met, the activity appears on top of the asset annotation in the 3D lens when the document is open.

#### Grid zones

Grid zones let you divide your 3D models and 2D documents into logical areas for easier navigation and activity mapping. When configured, users can view zones as overlays and navigate to specific zones from activities.

To link activities to grid zones, populate the `gridReference` property on activities. Use the naming convention `[deck level]_[grid zone]` with an underscore separator, for example, `LEVEL1_GRID-10`. This ensures uniqueness across deck levels and allows Maintain to update both attributes when mapping activities to zones.

##### 3D grid zones

3D grid zones use a JSON file stored in CDF Files to define the zone bounding boxes. You need one JSON file per location.

<Steps>
  <Step title="Add grid zones in Feature Configuration">
    Set `"enableGridZones"` to `true` in Feature Configuration:

    ```json theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
    "threeDConfiguration": {
      "enableGridZones": true
    }
    ```
  </Step>

  <Step title="Create a grid zones file">
    Create a JSON file containing the zone definitions. Each zone requires a `zone` identifier and 3D bounding box coordinates with `min` and `max` points (x, y, z):

    ```json theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
    {
      "zones": [
        {
          "zone": "LEVEL1_GRID-10",
          "min": [20000.019, 30.6, -10021.994],
          "max": [20016.019, 39.2, -10031.994]
        },
        {
          "zone": "LEVEL1_GRID-11",
          "min": [20016.019, 30.6, -10021.994],
          "max": [20032.019, 39.2, -10031.994]
        }
      ]
    }
    ```

    | Property | Description                                                                                                                                                 |
    | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | `zone`   | The unique identifier for the zone. Use the `[deck level]_[grid zone]` naming convention. This value must match the `gridReference` property on activities. |
    | `min`    | The minimum corner of the bounding box as `[x, y, z]` coordinates in 3D model space.                                                                        |
    | `max`    | The maximum corner of the bounding box as `[x, y, z]` coordinates in 3D model space.                                                                        |

    <Note>
      Coordinates are absolute positions in the 3D model's coordinate system. Optional properties `floc` (functional location) and `platform` can also be included.
    </Note>
  </Step>

  <Step title="Upload the file to CDF">
    Upload the JSON file to CDF Files and note its external ID. Create one file per location.
  </Step>

  <Step title="Link the file to your location">
    In the Root Location Configuration, add the `gridZonesFileId` property with the external ID of the uploaded file:

    ```json theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
    {
      "locations": [
        {
          "label": "Site A",
          "value": "SITE_A",
          "modelId": 1234,
          "revisionId": 5678,
          "gridZonesFileId": "grid-zones-site-a"
        }
      ]
    }
    ```
  </Step>
</Steps>

##### 2D grid zones

2D grid zones use data modeling to define zone areas in documents.

<Steps>
  <Step title="Add grid zones in Feature Configuration">
    Set `"enabled"` to `true` in Feature Configuration:

    ```json theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
    "gridZones2dConfiguration": { "enabled": true }
    ```
  </Step>

  <Step title="Populate the grid zones data model">
    Add zone annotation data to the `MaintainFileGridZoneAnnotations` view in your app data space. Each zone annotation links a zone to a specific area in a document:

    | Property        | Description                                                                                                                        |
    | --------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
    | `externalId`    | A unique identifier. Use the convention `[rootLocation]_[deck]_[grid]`.                                                            |
    | `space`         | The app data instance space for your location.                                                                                     |
    | `fileReference` | The external ID of the document containing the zone.                                                                               |
    | `rootLocation`  | The root location identifier. Must match the `rootLocation` property on activities.                                                |
    | `zone`          | The zone identifier using the `[deck level]_[grid zone]` naming convention. Must match the `gridReference` property on activities. |
    | `x1`, `y1`      | The coordinates of the first corner of the zone rectangle (normalized 0-1).                                                        |
    | `x2`, `y2`      | The coordinates of the opposite corner of the zone rectangle (normalized 0-1).                                                     |

    <Tip>
      If you're using the Cognite Toolkit, create nodes in the `Maintain_FileGridZoneAnnotation` view. See examples in your toolkit data under `build/data_modeling/` directory.
    </Tip>

    <Note>
      Coordinates are normalized values between 0 and 1, representing the position relative to the document dimensions. For example, `x1: 0.1` means 10% from the left edge of the document, and `(0, 0)` represents the top-left corner.
    </Note>
  </Step>
</Steps>

#### 2D viewer

The 2D viewer functionality is added by default. To remove this functionality, set `"disabled"` to `true` in Feature Configuration:

```json theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
"canvasConfiguration": { "disabled": true }
```

By default, all supported documents ingested into the CDF project can be opened in Maintain. However, additional configuration is required to fully use the 2D features.

<Tip>
  Learn how to [parse and extract data from P\&ID diagrams](/cdf/integration/guides/contextualization/parse_diagrams) to automatically link assets to diagram elements.
</Tip>

#### Supported document types

Maintain supports the `application/pdf` MIME type (Multimedia Internet Mail Extensions) documents. Other document types won't appear in the search in Maintain.

<Note>
  All files must have an external ID. Files without an external ID can't be opened.
</Note>

##### Document type resolution

Maintain resolves the document type differently depending on whether your environment uses the **Industry Data Model (IDM)** or **metadata-based** configuration.

<Tabs>
  <Tab title="IDM environments">
    Maintain reads the document type from the `category.code` property on the [`CogniteFile`](/cdf/dm/dm_reference/dm_core_data_model#file) concept in the CDF Core Data Model.

    If `category.code` is not set or empty, Maintain falls back to the metadata-based resolution described below.
  </Tab>

  <Tab title="Metadata-based environments">
    Maintain reads the document type from file metadata using this order of precedence:

    1. The value at the metadata key defined in `featureConfiguration.canvasConfiguration.fileTypeMetadataKey`.
    2. If that key is not configured or the value is missing, the default metadata key `"Type"` is used.

    <Note>
      `category.code` is ignored even if present on the file.
    </Note>
  </Tab>
</Tabs>

<br />

##### Migration: metadata to IDM document types

Maintain currently supports both paths for backward compatibility during the transition to IDM.

* **IDM environments** — set the `category.code` property on [`CogniteFile`](/cdf/dm/dm_reference/dm_core_data_model#file) nodes to classify documents. If `category.code` is not yet populated, Maintain falls back to metadata-based classification automatically.
* **Metadata-based environments** — no action required. Metadata-based classification continues to work without changes.
* **Future** — once all environments are migrated to IDM, the metadata-based classification path will be removed.

##### Document naming and grouping

Documents can be grouped by their type. By default, documents have the `Unknown` type. Maintain supports the following types without additional configuration, but other types can be added on request:

| Type value | Description          |
| ---------- | -------------------- |
| LAY        | Layout diagram       |
| PID        | P\&ID                |
| PLT        | Plot plans           |
| SLD        | Single-line diagrams |
| UNK        | Unknown              |

<Note>
  The document type is used for logical grouping only and doesn't affect how Maintain interacts with documents.
</Note>

In CDF, the metadata fields for documents in Maintain are `Name` for the document title and `Title` for the document description.

#### Risks

Risks are displayed in the asset inspector under the **Risks** tab. Maintain supports one risk type (`Risk`) in the Industry data model (IDM).

To remove the Risks tab from the asset inspector, use the `inspectorConfiguration` in Feature Configuration:

```json theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
"inspectorConfiguration": {
  "excludedInspectorTabs": [
    { "title": "Risks", "view": "asset" }
  ]
}
```

#### Layout

To add layouts, set `"enableCustomLayouts"` to `true` in Feature Configuration:

```json theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
"enableCustomLayouts": true
```

This also requires the presence of the `activeColorCoding` attribute in the `MaintainLayout` view (data model Maintain).

```javascript theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
type MaintainLayout {
  ...
  activeColorCoding: String
  ...
}
```

<Note>
  To create global layouts visible to all users, you need write access to `APM_Config`. Users without this access can only create personal layouts.
</Note>

##### Column order and column widths

Layouts can persist not only which columns are visible but also the **column order** (left-to-right arrangement) and **column widths** (horizontal size of each column). Both properties are optional and controlled by feature toggles.

The following table shows how the toggle states affect layout behavior:

| Column order toggle | Column widths toggle | Result                                                                                                        |
| ------------------- | -------------------- | ------------------------------------------------------------------------------------------------------------- |
| OFF                 | OFF                  | Default: layouts store visibility only. Order and width come from the current field configuration at runtime. |
| ON                  | OFF                  | Layouts save and load column order. Column widths remain runtime-controlled.                                  |
| OFF                 | ON                   | Layouts save and load column widths. Column order remains runtime-controlled.                                 |
| ON                  | ON                   | Full persistence: layouts save and load both column order and column widths.                                  |

<Note>
  Existing layouts saved before enabling these toggles continue to work. When you select a layout that doesn't have column order or width data, Maintain automatically creates a baseline from the current field configuration. No data migration is required.
</Note>

**Enable column order and column widths**

To enable column order and width persistence for layouts, complete the following steps:

<Steps>
  <Step title="Update the data model view">
    The layout view must include the new properties. Depending on your environment:

    <Tabs>
      <Tab title="MaintainLayout (system)">
        If your environment uses the `MaintainLayout` view in the `cdf_maintain` space (v1), add the following properties to the view schema:

        * `columnsOrder` — optional array of strings.
        * `columnWidths` — optional array of objects with `fieldName` (string) and `width` (number).

        Deploy the view/schema change before or with the app version that writes these fields.
      </Tab>

      <Tab title="Maintain_Layout (custom/legacy)">
        If your environment uses the `Maintain_Layout` view in your app's data model space:

        1. Add `columnsOrder` (optional array of strings) to the view.
        2. Add `columnWidths` (optional array of objects with `fieldName` and `width`) to the view.
        3. Publish the updated view version.
        4. Deploy the schema change before or with the app version that writes these fields.
      </Tab>
    </Tabs>

    <Warning>
      If these properties are not present in the view definition, upserts may strip the values or fail. Deploy schema changes before enabling the feature toggles.
    </Warning>
  </Step>

  <Step title="Enable the feature toggles">
    Enable the following toggles for the target environment:

    | Toggle                           | Purpose                                              |
    | -------------------------------- | ---------------------------------------------------- |
    | `MAINTAIN_layouts_columns_order` | Enables saving and loading column order in layouts.  |
    | `MAINTAIN_layouts_column_widths` | Enables saving and loading column widths in layouts. |

    You can enable the toggles independently or together.
  </Step>

  <Step title="Validate">
    1. Open Maintain and select a layout.
    2. Reorder columns or resize them in the activity table.
    3. Save the layout and verify that the column order and widths persist when you reload or reselect the layout.
    4. Select a legacy layout (saved before enabling the toggles) and verify that it loads correctly with baseline column order and widths from the current field configuration.
  </Step>
</Steps>

**Disable column order and column widths**

To disable column order and width persistence, turn off the `MAINTAIN_layouts_columns_order` and `MAINTAIN_layouts_column_widths` toggles. The app immediately stops saving column order and widths with layouts and falls back to runtime field configuration. No data migration or cleanup is needed, as Maintain ignores stored column order and widths when the toggles are off.

#### Plan Analysis

To add Plan Analysis, set `"enablePlanAnalysis"` to `true` in Feature Configuration:

```json theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
"cabinetConfiguration": {
  "enablePlanAnalysis": true
}
```

When added, the **Plan Analysis** panel appears at the bottom of the screen for created plans. This panel provides insights into your maintenance plans, including budget calculations and hourly utilization.

<Note>
  Plan Analysis requires `personHours` and `numberOfMainResource` values in the `CogniteOperation` view when ingesting data into your data model.
</Note>

## Configure locations

Locations define the root assets and associated data spaces for your Maintain deployment. You can configure one or multiple locations within a single configuration, each with its own source data and application data spaces. When users sign in, they can select which location to work with and switch between locations as needed.

To configure locations, go to Maintain > ***your.Config*** > ***Feature Configuration*** and add entries to the `"rootLocationConfigurations"` array. Each location requires the following properties:

| Property                  | Description                                                                                                                    |
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `assetExternalId`         | The external ID of the root asset for this location.                                                                           |
| `displayName`             | Optional. A display name for the location shown in the location selector. If not provided, the `assetExternalId` is displayed. |
| `appDataInstanceSpace`    | The space where Maintain stores application data (plans, layouts) for this location.                                           |
| `sourceDataInstanceSpace` | The space where source data (from SAP or other systems) is stored for this location.                                           |

<Tabs>
  <Tab title="Single location">
    This example shows how to configure a single location:

    ```json theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
    "rootLocationConfigurations": [
      {
        "assetExternalId": "YourRootAsset",
        "displayName": "yourLocationName",
        "appDataInstanceSpace": "yourLocation_app_data",
        "sourceDataInstanceSpace": "yourLocation_source_data"
      }
    ]
    ```
  </Tab>

  <Tab title="Multiple locations">
    This example shows how to configure multiple locations:

    ```json theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
    "rootLocationConfigurations": [
      {
        "assetExternalId": "LOR_NORWAY",
        "displayName": "Norway",
        "appDataInstanceSpace": "norway_app_data",
        "sourceDataInstanceSpace": "norway_source_data"
      },
      {
        "assetExternalId": "LOR_SWEDEN",
        "displayName": "Sweden",
        "appDataInstanceSpace": "sweden_app_data",
        "sourceDataInstanceSpace": "sweden_source_data"
      }
    ]
    ```

    When multiple locations are configured, users see a location selector when signing in and can switch between locations from the configuration menu.
  </Tab>
</Tabs>

## Export activities

Maintain provides several export options for activities. The following export formats are always available:

| Format        | Description                                         | Limit           |
| ------------- | --------------------------------------------------- | --------------- |
| PDF           | Export activities as a PDF document.                | -               |
| CSV           | Export activities as a comma-separated values file. | 5000 activities |
| Excel (.xlsx) | Export activities as an Excel spreadsheet.          | 5000 activities |

<Note>
  Only fields with `enableInCsvImport` set to `true` in the [Field Configuration](#field-configuration) will be included in CSV and Excel exports.
</Note>
