Update a lifecycle

mutation ($patches:[Patch]!) {
 result:updateFactSheet(id:"142d61ce-3dfc-4516-a108-a871fbe3f929", patches:$patches, validateOnly:false) { 
   factSheet { 
     ... on Project {rev displayName 
       lifecycle{asString phases{phase startDate}}}
   }
 }
}

Query Variables:
{
  "patches":
    [{"op":"replace",
      "path":"/lifecycle",
      "value":"{\"phases\":[{\"phase\":\"plan\",\"startDate\":\"2017-03-12\"}]}"}]
}
{
  "data": {
    "result": {
      "factSheet": {
        "rev": 6,
        "displayName": "New Name",
        "lifecycle": {
          "asString": "plan",
          "phases": [
            {
              "phase": "plan",
              "startDate": "2017-03-12"
            }
          ]
        }
      }
    }
  },
  "errors": null
}

In case there already are values defined on the lifecycle field, those will need to be provided inside the mutation variables as well. If not, the existing values will be overwritten by the provided values in the mutation. For an example, see below.

Query Variables:
{
  "patches":
    [{"op": "replace",
      "path": "/lifecycle",
      "value": "{\"phases\":[{\"phase\":\"plan\",\"startDate\":\"2017-03-12\"},{\"phase\":\"phaseIn\",\"startDate\":\"2022-07-01\"}]}"
}

Alternatively you can also use a different structure in the variables, targeting a specific phase only. See example below.

{
  "patches": [
    {
      "op": "replace",
      "path": "/lifecycle/phaseIn",
      "value": "2022-07-01"
    }
  ]
}

Add Tags

Add a tag to a Fact Sheet

Add text, create a new tag in "other tags" and add a tag to the Fact Sheet.

mutation ($patches: [Patch]!) {
  result: updateFactSheet(id: "142d61ce-3dfc-4516-a108-a871fbe3f929", patches: $patches, validateOnly: false) {
    factSheet {
      ... on Application {
        rev
        displayName
        tags {
          id
          name
          color
          description
          tagGroup {
            shortName
          }
        }
      }
    }
  }
}

Query Variables:
{"patches":[{"op":"add","path":"/tags","value":"[{\"tagName\":\"development\"}]"}]}
{
  "data": {
    "result": {
      "factSheet": {
        "rev": 7,
        "displayName": "New Name",
        "tags": [
          {
            "id": "7fd035ea-e3a0-4689-8a55-b0bd0330326f",
            "name": "development",
            "color": "#D8D8D8",
            "description": null,
            "tagGroup": null
          }
        ]
      }
    }
  },
  "errors": null
}

Add existing Tag to a Fact Sheet

Add a specific tag to a factsheet

mutation ($patches: [Patch]!) {
  result: updateFactSheet(id: "28fe4aa2-6e46-41a1-a131-72afb3acf256", patches: $patches, validateOnly: false) {
    factSheet {
      ... on Application {
        rev
        displayName
        tags {
          id
          name
          color
          description
          tagGroup {
            shortName
          }
        }
      }
    }
  }
}

Query Variables:
{"patches":[{"op":"add","path":"/tags","value":"[{\"tagId\":\"ed12c323-3bbd-4f8d-a024-70ff409c978a\"}]"}]}
{
  "data": {
    "result": {
      "factSheet": {
        "rev": 11,
        "displayName": "AC Management",
        "tags": [
          {
            "id": "ed12c323-3bbd-4f8d-a024-70ff409c978a",
            "name": "Infoserve",
            "color": "#999999",
            "description": null,
            "tagGroup": {
              "shortName": null
            }
          }
        ]
      }
    }
  },
  "errors": null
}

Add a document to a Fact Sheet

mutation {
  createDocument(factSheetId: "1e4ea87e-5302-4de9-bbbc-166c882c2660", name: "Link to Other Source", url: "https://leanix.net", description: "This is a link", validateOnly: false) {
    id
    name
    description
    factSheetId
  }
}
{
  "data": {
    "createDocument": {
      "id": "1c1d9c7f-84e7-41b1-b484-1900a2b6f50e",
      "name": "Link to Other Source",
      "description": "This is a link",
      "factSheetId": "1e4ea87e-5302-4de9-bbbc-166c882c2660",
      "fileInformation": null
    }
  },
  "errors": null
}

Manage Subscriptions

Add a subscription to a Fact Sheet

You will need to provide a valid userId or email attribute, not necessarily both.

mutation {
  createSubscription(factSheetId: "1e4ea87e-5302-4de9-bbbc-166c882c2660", user: {id: "61f5e606-327d-4d1f-a65b-62f18e265efc", userName: "[email protected]"}, type: RESPONSIBLE, validateOnly: false, roleIds: ["f81acd26-aa82-4e4d-a2ea-e2d21e646582"]) {
    id
    user {
      userName
    }
    type
    roles {
      id
      name
      subscriptionType
    }
    createdAt
    factSheet {
      id
    }
  }
}
{
  "data": {
    "createSubscription": {
      "id": "3a004cbb-7679-4f6a-bab1-537ef99df900",
      "user": {
        "userName": "[email protected]"
      },
      "type": "RESPONSIBLE",
      "roles": [
        {
          "id": "f81acd26-aa82-4e4d-a2ea-e2d21e646582",
          "name": "Product Owner",
          "subscriptionType": "RESPONSIBLE"
        }
      ],
      "createdAt": "2017-09-27T09:38:46.074Z",
      "factSheet": {
        "id": "1e4ea87e-5302-4de9-bbbc-166c882c2660"
      }
    }
  },
  "errors": null
}

Remove an existing subscription

Get the subscriptions for a Fact Sheet:

{
  factSheet(id: "6d6bae96-c745-47b0-8a41-b850d90958d1") {
    subscriptions {
      edges {
        node {
          id
          user {
            id
            userName
          }
          roles {id subscriptionType}
        }
      }
    }
  }
}

Now, use the fetched subscription ID (directly beyond node) to delete the subscription:

mutation {
  deleteSubscription(id: "c92689fd-2d00-489a-8d4e-eaa28bebc904") {
    id
    name
  }
}

Get archived fact sheets

e.g. by display name

query allFactSheetsQuery ($filter: FilterInput!) {
  allFactSheets(first: 40, filter: $filter) {
    edges {
      node {
        id
        displayName
        type
      }
    }
  }
}

Query Variables:
{"filter":
   {"responseOptions":{"maxFacetDepth":5},
    "facetFilters":
      [{"facetKey":"TrashBin","operator":"OR","keys":["status"]},{"facetKey":"FactSheetTypes","operator":"OR","keys":["UserGroup"]}], "displayName" :"name"}}
{
  "data": {
    "allFactSheets": {
      "edges": [
        {
          "node": {
            "id": "5e85b861-97f7-4b87-987e-7566694d8fdf",
            "displayName": "Australia",
            "type": "UserGroup"
          }
        }
      ]
    }
  },
  "errors": null
}

Relation validity filtering

What is Relation validity?

Relation validity ("activeFrom" and "activeUntil") is the time interval during which a Relation
between Fact Sheets is deemed to exist. The two values are dates in ISO format like 2018-07-01
(no time).
Any of them may be unspecified,
which means the Relation validity is not bounded in this direction of time. If both of these values
of the Relation are not set, then the Relation is considered to always exist.

How are Relations filtered by their validity?

For this purpose, the DateFilterInput argument type contains the fields from and to and the
DateFilterType in field type.

These are the possible values of the type field:

  • Of main importance is only the date filter type RANGE.
  • RANGE_START and RANGE_ENDS are not implemented for Relation validity filtering and behave like
    RANGE for now.
  • POINT behaves like RANGE, but the given value for to is ignored and always considered
    to be equal to from.
  • TODAY, END_OF_MONTH, and END_OF_YEAR are special cases of POINT where the given values of
    from and to are ignored and considered to be equal to the day corresponding to the type.

The values of the fields from and to are dates in ISO format (no time) and define the filter interval. Any of the two values may
be null, meaning the interval is unbounded in that direction.

The Relation validity filtering semantics is the following:

A Relation is matched by the filter if and only if the Relation validity interval has a non-empty
intersection with the filter interval.
In other words, if the time span defined by the
Relation's activeFrom and activeUntil fields
and the time span defined by the filter's from and to fields overlap.

Where can Relation validity be filtered?

In the GraphQL API, filtering for relation validity is available at the following spots:

  1. in the relation facets (filter ->facetFilter -> dateFilter argument of the allFactSheets
    top level query field)

    Note: For now, instead of the dateFilter on the individual relation facets, the dateFilter on the
    lifecycle facet is used. This will change in a future version. The key field of this lifecycle filter facet is ignored for the purpose of relation validity filtering.

    Example:

{
     allFactSheets(filter:
       {facetFilters: [
         {facetKey:"FactSheetTypes" keys:["UserGroup"]}
         {facetKey: "relUserGroupToApplication" keys: ["e3a08f5f-5c3e-4dc1-8444-ed87bdd48634"]}
         {facetKey:"lifecycle" keys:"__any__" dateFilter:{type:RANGE from:"2018-07-01" to:"2018-07-31"}}
       ]})
     {
       edges {
         node {
           type
           displayName
         }
       }
     }
   }
  1. in the relation validity filter

    This is a filter that restricts the Relations that are returned in the relation fields of
    a concrete Fact Sheet type, for example, field relApplicationToUserGroup in type
    Application. Those fields accept an argument validityFilter containing the fields
    activeFrom and activeUntil, which behave like from and to in DateFilterInput (see above).

    Example:

{
     factSheet(id: "e3a08f5f-5c3e-4dc1-8444-ed87bdd48634") {
       displayName
       ... on Application {
         relApplicationToUserGroup(validityFilter: {activeFrom: "2018-07-01", activeUntil: "2018-07-31"}) {
           edges {
             node {
               activeFrom
               factSheet {
                 displayName
               }
             }
           }
         }
       }
     }
   }

Setting the quality seal of a fact sheet

The quality seal of a fact sheet can be either "approved" or "broken". With this mutation, you can set the quality seal of a fact sheet to approved.

mutation ($patches: [Patch]!) {
  result: updateFactSheet(id: "4b49c052-3f38-49be-a429-53548786814d", patches: $patches, validateOnly: false) {
    factSheet {
      rev
      qualitySeal
    }
  }
}

Query Variables:
{
  "patches":
    [{"op":"replace",
      "path":"/qualitySeal",
      "value":"approve"}]
}

❗️

The "replace" Operation

Using "replace" instead of "add" will essentially replace all existing values with whatever is specified in the "value" argument of the mutation. As such please use with caution!

In the example above it is logical to utilize the "replace" operation. However, there are instances where utilizing "replace" is not preferable due to the nature of how it works.

Create and update a Fact Sheet

mutation ($input: BaseFactSheetInput!, $patches: [Patch]!) {
  createFactSheet(input: $input, patches: $patches) {
    factSheet {
      id
      name
      description
      type
    }
  }
}

{
  "input":{"name":"New Fact Sheet", "type": "Application"},
  "patches": [{"op":"replace","path":"/description","value":"New Description"}]
}

Send multiple mutations by call

In order to increase performance impact e.g. by network latency, you can summarize more than one mutation into one call by using mutation aliases.

🚧

Important

Make sure to choose a unique alias per mutation.

Make sure to separate your mutations into chunks, as http timeouts might influence execution otherwise. Depending on the complexity of the single mutations, 50 might be a reasonable chunk size to start with.

mutation {
  fs1: createFactSheet(input: {name: "fs1", type:Application}) {
    factSheet { id }
  },
  fs2: createFactSheet(input: {name: "fs2", type:Application}) {
    factSheet { id }
  }
}