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

# Take training

Once a user is enrolled to the Learning Path through a membership, they can start the training by creating a Learning Path Attempt.
This attempt serves as a persistent container for all user interactions and progress throughout the Learning Path.
All responses and data submitted by the user should be stored under the Attempt ID returned from the API call.

The CTA with the action ID `CREATE_LP_ATTEMPT` will be returned in the `NavigationItem` CTA list.
This CTA is available for all non-locked `NavigationItems` of contentType `MODULE`.

<CodeGroup>
  ```GraphQL GraphQL theme={null}
  query getLearningPath {
    getLearningPath(lpId: 40) {
      userEnrolled
      navigation(navigationType: FULL_NAVIGATION) {
        edgeId
        edgeRid
        title
        description
        contentType
        navigationPath
        locked
        lockReasons
        learningContentType
        cta {
          title
          actionId
          arguments {
            key
            value
          }
          metadata {
            key
            value
          }
        }
      }
    }
  }
  ```

  ```Query Query result [expandable] theme={null}
  {
      "data": {
          "getLearningPath": {
              "userEnrolled": true,
              "navigation": [
                  {
                      "edgeId": "116",
                      "edgeRid": "488",
                      "title": "Target Results of 2024",
                      "description": "<p>Distinctively leverage other's viral initiatives and open-source deliverables. Globally morph ubiquitous vortals vis-a-vis go forward leadership. Quickly synthesize focused \"outside the box\" thinking via resource-leveling communities. Quickly synergize team building expertise with pandemic action items. Distinctively engage team building expertise.</p>",
                      "contentType": "MODULE",
                      "navigationPath": null,
                      "locked": false,
                      "lockReasons": [],
                      "learningContentType": "QUIZ",
                      "cta": [
                          {
                              "title": "Start",
                              "actionId": "CREATE_LP_ATTEMPT",
                              "arguments": [
                                  {
                                      "key": "lpId",
                                      "value": "40"
                                  },
                                  {
                                      "key": "edgeRid",
                                      "value": "488"
                                  }
                              ],
                              "metadata": [
                                  {
                                      "key": "type",
                                      "value": "button"
                                  }
                              ]
                          }
                      ]
                  },
                  {
                      "edgeId": "117",
                      "edgeRid": "481",
                      "title": "The OPS",
                      "description": null,
                      "contentType": "ACTIVITY",
                      "navigationPath": "116:117",
                      "locked": false,
                      "lockReasons": [],
                      "learningContentType": "QUIZ",
                      "cta": []
                  },
                  {
                      "edgeId": "118",
                      "edgeRid": "482",
                      "title": "The DEV",
                      "description": null,
                      "contentType": "ACTIVITY",
                      "navigationPath": "116:118",
                      "locked": true,
                      "lockReasons": [],
                      "learningContentType": "QUIZ",
                      "cta": []
                  },
                  {
                      "edgeId": "119",
                      "edgeRid": "485",
                      "title": "Future goals",
                      "description": null,
                      "contentType": "MODULE",
                      "navigationPath": null,
                      "locked": true,
                      "lockReasons": [
                          "Complete prior module"
                      ],
                      "learningContentType": "QUIZ",
                      "cta": []
                  },
                  {
                      "edgeId": "120",
                      "edgeRid": "486",
                      "title": "Best practices",
                      "description": null,
                      "contentType": "ACTIVITY",
                      "navigationPath": "119:120",
                      "locked": true,
                      "lockReasons": [],
                      "learningContentType": "QUIZ",
                      "cta": []
                  }
              ]
          }
      }
  }
  ```
</CodeGroup>

## Create learning path attempt

`CREATE_LP_ATTEMPT` CTA indicates that the module can be started by execution of `createLpAttempt`
mutation with the arguments provided in the corresponding CTA arguments.

<CodeGroup>
  ```GraphQL GraphQL theme={null}
  mutation createLpAttempt {
    createLpAttempt(lpId: 40, edgeRid: 488) {
      response {
        cta {
          actionId
          arguments {
            key
            value
          }
        }
      }
    }
  }
  ```

  ```Query Query result theme={null}
  {
    "data": {
      "createLpAttempt": {
        "response": {
          "cta": [
            {
              "actionId": "TAKE_EDGE",
              "arguments": [
                {
                  "key": "lpId",
                  "value": "40"
                },
                {
                  "key": "lpAttemptContextId",
                  "value": "2396"
                },
                {
                  "key": "edgeRid",
                  "value": "481"
                }
              ]
            }
          ]
        }
      }
    }
  }
  ```
</CodeGroup>

In the mutation response, you will receive a CTA with the action ID `TAKE_EDGE`,
which indicates that the user should now be redirected to the Learning Path take interface.

<Note>
  **Note**: Once a Learning Path Attempt is successfully created, the
  `CREATE_LP_ATTEMPT` CTA will be replaced with `TAKE_EDGE` CTA.
</Note>

## Take modules when learning path attempt is created

Opigno Enterprise API provides the embed URL to display a rendered activity form inside a module.
The `getLearningPathContentData` query provides the key data needed to render the embedded activity section. It returns two primary elements:

* **CTA list** – a list of available call-to-action objects, such as `SAVE_ANSWER` or `TAKE_EDGE`,
  that primarily act as form controls.
* **embeddedUrl** – the URL used to load the learning activity inside an iframe.

The `embeddedUrl` seen in the response is the main gateway to let the user perform an activity.
It should be used to display an activity form in iframe:

```
<iframe src="{{ getLearningPathContentData.embeddedUrl }}"></iframe>
```

## Submit an activity answer

Submitting a training step involves the following sequence:

* Rendering the activity iframe
* Subscribing to the `message` event on the `document`
* Submitting user answers via the `saveAnswer` mutation

Once the iframe is rendered, you should subscribe to the `message` event.
When the user completes the activity inside the iframe, a message is sent to the parent window.

The activity completion message contains a `type`, which can be one of the following:

* `activityAttemptResult`
* `activityAttemptFeedback`

The `activityAttemptFeedback` type is specific and only used in certain configurations for limited activities.
For more details, see the [next section](#submit-an-activity-answer-with-“display-results-and-feedback”-option-enabled). In most cases, you will receive the `activityAttemptResult` message type.

<Warning>
  **We strongly recommend delaying the execution of the **`saveAnswer`** mutation
  until the complete result message is received from the iframe.**

  This means the answer should be sent to the API only when the user's activity is fully processed before submission.
</Warning>

Within the message received from the iframe, the following information is included:

* `answer` — the user's answer.
* `order` — internal metadata, specific to some activity types.
* `activityType` — the activity type.

<Note>
  The information received from the iframe **must not be modified**. It should be passed back unchanged within the `answerData` payload.
</Note>

Once the completion message is received, you need to construct the `answerData` payload required for the `saveAnswer` mutation.
This payload is typically unified across all activity types and should include:

* `answer` — the `answer` value from the iframe message.
* `order` — the `order` value from the iframe message.
* `lpAttemptContextId` — the Learning Path Attempt Context ID (provided by the client routing system).
* `edgeRid` — the Edge Revision ID (provided by the client routing system).
* `attemptStatus` — usually it should be `COMPLETED`. Since the triggering of the save action occurs on the client side, this value should also be provided by the client.
* `activityType` — the `activityType` value from the iframe message.

Below is an example of the `saveAnswer` mutation for SCORM activity:

<CodeGroup>
  ```filename GraphQL theme={null}
  mutation saveAnswer {
    saveAnswer(answerData: {
      answer: "{\"score\":\"100\",\"scaled_score\":\"1\",\"min_score\":\"0\",\"max_score\":\"100\",\"completion_status\":\"completed\",\"type\":\"scormAttemptResult\"}",
      order: NULL,
      lpAttemptContextId: 2396,
      edgeRid: 481,
      attemptStatus: COMPLETED,
      activityType: SCORM
    }) {
      errors
      response {
        cta {
          actionId
          arguments {
            key
            value
          }
        }
      }
    }
  }
  ```

  ```File Query result theme={null}
  {
    "data": {
      "saveAnswer": {
        "errors": [],
        "response": {
          "cta": [
            {
              "actionId": "TAKE_EDGE",
              "arguments": [
                {
                  "key": "lpId",
                  "value": "40"
                },
                {
                  "key": "lpAttemptContextId",
                  "value": "2396"
                },
                {
                  "key": "edgeRid",
                  "value": "482"
                }
              ],
            }
          ]
        }
      }
    }
  }
  ```
</CodeGroup>

In the example above, the mutation response includes a `TAKE_EDGE` CTA, which indicates that the user should be redirected to the next activity.

<Note>
  If the current activity is the last one in the module, the system will return a `VIEW_RESULTS` CTA,
  indicating that the module is finished and the next step is the edge result screen.

  If there is no next step, it means that the activity is the last within the Learning Path and the API will return
  `VIEW_LP` CTA, indicating that the user should be redirected to the Learning Path homepage.
</Note>

## Submit an activity answer with "Display results and feedback" option enabled

Some activities, such as **TRUE/FALSE** or **MULTIPLE\_CHOICE**, support displaying
of the results and feedback immediately after the answer is saved.
To enable this functionality, the *"Display results and feedback"* setting for the activity must be enabled.

<Note>
  The `activityAttemptFeedback` message type indicates that the *"Display results and feedback"*
  option is enabled for this activity. When this message type is received, the system should display
  the attempt results and feedback to the learner as a part of the activity flow.
</Note>

For these types of activities, the `saveAnswer` process works the same way as for other activities.
The difference lies in the iframe message type which in this case will be `activityAttemptFeedback`,
and in the available CTAs returned by the API. See the `saveAnswer` mutation example below:

<CodeGroup>
  ```filename GraphQL theme={null}
  mutation saveAnswer {
    saveAnswer(answerData: {
      answer: "[\"0\"]",
      order: "[\"0\",\"1\",\"2\"]",
      lpAttemptContextId: 529,
      edgeRid: 884,
      attemptStatus: COMPLETED,
      activityType: MULTIPLE_CHOICE
    }) {
      errors
      response {
        cta {
          actionId
          arguments {
            key
            value
          }
          metadata {
            key
            value
          }
        }
      }
    }
  }
  ```

  ```File Query result [expandable] theme={null}
  {
    "data": {
      "saveAnswer": {
        "errors": [],
        "response": {
          "cta": [
            {
              "actionId": "TAKE_EDGE",
              "arguments": [
                {
                  "key": "lpId",
                  "value": "10"
                },
                {
                  "key": "lpAttemptContextId",
                  "value": "529"
                },
                {
                  "key": "edgeRid",
                  "value": "885"
                }
              ],
              "metadata": []
            },
            {
              "actionId": "REVIEW_EDGE_EMBED",
              "arguments": [],
              "metadata": [
                {
                  "key": "src",
                  "value": "http://opigno4-project.docksal.site/opigno-activity/embed/529/884/review"
                }
              ]
            }
          ]
        }
      }
    }
  }
  ```
</CodeGroup>

In this case, `REVIEW_EDGE_EMBED` CTA is returned in the `saveAnswer` response.
This means that you need to replace the iframe URL with the value provided in the `src` key of the `REVIEW_EDGE_EMBED` CTA,
in order to display the activity results and feedback.

<Note>
  At this moment the answer is already saved.
</Note>

The URL for the next step should be constructed using the data available from one of the CTAs in the `saveAnswer` response:
either `VIEW_RESULTS` or `TAKE_EDGE`, depending on the current activity's position within the module.
