Skip to content

Loading Projects

The Project Configurator service is capable of creating Projects with nested folders, plans, assortments, showcases, and boards. With the use of identifiers on all of these entities we are able to both create and update using this service. The service accepts relationships and properties for all of the entities as well.

Service DTO

ProjectConfiguration

export class ProjectConfiguration {
  projectName: string;
  identifier: string;
  principals: string[];
  commonConfig: CommonConfiguration;
  assortments: AssortmentConfiguration[];
  subFolders: Folder[];
}
  • identifier: This will be used as the federatedId to update or create the project. THIS SHOULD BE UNIQUE FOR THE ENTIRE ORG.

  • projectName: Used to set the name of the project.

  • principals: A list of group names and user emails that are allowed in the project with roles attached to each. i.e. [“Global Merch|ADMIN”, “EMEA|MEMBER”, “btp@vibeiq.com|ADMIN”]

  • commonConfig: This is a json blob that can hold any property. Any property that is defined in the commonConfig can be referenced in any string throughout the rest of the template by using {}.

i.e. If the commonConfig had a property ‘season’ set to 'Fall 2020' you can reference it like this:

“{season} - Global”. This will result in “Fall 2020 - Global”.

  • assortments: This is the list of assortments you wish to have at the project root level. An assortment can be created on its own or it can have an associated plan, board, or showcase. This is described further down below.

  • subFolders: This describe the subfolders you want to be created at the root level. A subfolder can have nested subfolders of its own, along with assortments at all the nested levels.

AssortmentConfiguration

export class AssortmentConfiguration {
  identifier: string;
  name: string;
  type: AssortmentType;
  sourceAssortmentIdentifier?: string;
  composedFromAssortmentIdentifiers?: string[];
  ownerAtts?: {[key: string]: any};
  assortmentAtts?: {[key: string]: any};
}
  • identifier: This will be used as the federatedId to update or create the assortment or assortment owner. THIS SHOULD BE UNIQUE FOR THE ENTIRE ORG.

  • name: Used to set the name of the assortment and assortment owner name.

  • type: The available assortment types are “ASSORTMENT“ which is assortment only, “BOARD”, “PLAN”, and “SHOWCASE“ which will create the owner and an assortment.

  • sourceAssortmentIdentifier: This is the identifier of the assortment you want to set as the source to this assortment. If it is not restricted, leave this empty. NOTE: This is the identifier of the explicitly created Entity. Even if it is type "PLAN" it will use the assortment associated with the plan.

  • composedFromAssortmentIdentifiers: These are the identifiers of the assortments you want to set as the children of this assortment. If this is not a composite assortment, leave this empty. NOTE: These are the identifiers of the explicitly created Entities. Even if it is type "PLAN" it will use the assortment associated with the plan.

  • ownerAtts: This is a json blob of properties that should be put on the assortment owner (The plan, board, or showcase). Leave this blank if you dont wish to add extra properties.

  • assortmentAtts: This is a json blob of properties that should be put on the assortment. Leave this blank if you dont wish to add extra properties.

NOTE: Assortments can have a relationship with other assortments created at any level.

Folder

export class Folder {
  identifier: string;
  name: string;
  principals: string[];
  assortments: AssortmentConfiguration[];
  subFolders: Folder[];
}
  • identifier: This will be used as the federatedId to update or create the folder. THIS SHOULD BE UNIQUE FOR THE ENTIRE ORG.

  • name: Used to set the name of the folder.

  • principals: A list of group names and user emails that are allowed in the project with roles attached to each. i.e. [“Global Merch|ADMIN”, “EMEA|MEMBER”, “btp@vibeiq.com|ADMIN”]

  • assortments: This is the list of assortments you wish to have at this folder root level.

  • subFolders: This describe the subfolders you want to be created at this folder root level.

API Usage

To use this api the caller must be an org admin.

The url is "https://api.vibeiq.com/prod/api/project-configurator" and the only call type supported is POST. In the example below replace "PROJECT_IDENTIFIER" with actual project identifier and "PROJECT_NAME" with actual project name. The project configuration obj used below is just for reference and can be configured according to the needs.

import { Entities, Request, Types } from "@contrail/sdk";
const projectConfiguration = {
  "projectName": "{projectName}",
  "identifier": "{projectIdentifier}",
  "commonConfig": {
    "projectIdentifier": "PROJECT_IDENTIFIER",
    "projectName": "PROJECT_NAME"
  },
  "subFolders": [
    {
      "name": "Apparel",
      "identifier": "{projectIdentifier}:apparel.folder",
      "assortments": [
        {
          "identifier": "{projectIdentifier}:apparel:global.plan",
          "name": "{projectName} Apparel Global",
          "type": "PLAN",
          "assortmentAtts": {
            "typePath": "item:product:apparel",
            "identifier": "{projectIdentifier}:apparel:global.assortment"
          }
        }
      ]
    },
    {
      "name": "Accessories",
      "identifier": "{projectIdentifier}:accessories.folder",
      "assortments": [
        {
          "identifier": "{projectIdentifier}:accessories:global.plan",
          "name": "{projectName} Accessories Global",
          "type": "PLAN",
          "assortmentAtts": {
            "typePath": "item:product:accessories",
            "identifier": "{projectIdentifier}:apparel:global.assortment"
          }
        }
      ]
    },
    {
      "name": "Equipment",
      "identifier": "{projectIdentifier}:equipment.folder",
      "assortments": [
        {
          "identifier": "{projectIdentifier}:equipment:global.plan",
          "name": "{projectName} Equipment Global",
          "type": "PLAN",
          "assortmentAtts": {
            "typePath": "item:product:equipment",
            "identifier": "{projectIdentifier}:equipment:global.assortment"
          }
        }
      ]
    },
    {
      "name": "Footwear",
      "identifier": "{projectIdentifier}:footwear.folder",
      "assortments": [
        {
          "identifier": "{projectIdentifier}:footwear:global.plan",
          "name": "{projectName} Footwear Global",
          "type": "PLAN",
          "assortmentAtts": {
            "typePath": "item:product:footwear",
            "identifier": "{projectIdentifier}:footwear:global.assortment"
          }
        }
      ]
    }
  ]
}
await Request.request("/project-configurator", {
  method: "POST",
  body: JSON.stringify(projectConfiguration),
  headers: {
    Accept: "application/json",
    "Content-Type": "application/json",
  },
})
curl --request POST \
  --url https://api.vibeiq.com/prod/api/project-configurator
  --header 'Content-Type: application/json' \
  --header 'X-Api-Key: API_KEY' \
  --header 'X-Api-Org: ORG_KEY' \
  --data '{
  "projectName": "{projectName}",
  "identifier": "{projectIdentifier}",
  "commonConfig": {
    "projectIdentifier": "PROJECT_IDENTIFIER",
    "projectName": "PROJECT_NAME"
  },
  "subFolders": [
    {
      "name": "Apparel",
      "identifier": "{projectIdentifier}:apparel.folder",
      "assortments": [
        {
          "identifier": "{projectIdentifier}:apparel:global.plan",
          "name": "{projectName} Apparel Global",
          "type": "PLAN",
          "assortmentAtts": {
            "typePath": "item:product:apparel",
            "identifier": "{projectIdentifier}:apparel:global.assortment"
          }
        }
      ]
    },
    {
      "name": "Accessories",
      "identifier": "{projectIdentifier}:accessories.folder",
      "assortments": [
        {
          "identifier": "{projectIdentifier}:accessories:global.plan",
          "name": "{projectName} Accessories Global",
          "type": "PLAN",
          "assortmentAtts": {
            "typePath": "item:product:accessories",
            "identifier": "{projectIdentifier}:apparel:global.assortment"
          }
        }
      ]
    },
    {
      "name": "Equipment",
      "identifier": "{projectIdentifier}:equipment.folder",
      "assortments": [
        {
          "identifier": "{projectIdentifier}:equipment:global.plan",
          "name": "{projectName} Equipment Global",
          "type": "PLAN",
          "assortmentAtts": {
            "typePath": "item:product:equipment",
            "identifier": "{projectIdentifier}:equipment:global.assortment"
          }
        }
      ]
    },
    {
      "name": "Footwear",
      "identifier": "{projectIdentifier}:footwear.folder",
      "assortments": [
        {
          "identifier": "{projectIdentifier}:footwear:global.plan",
          "name": "{projectName} Footwear Global",
          "type": "PLAN",
          "assortmentAtts": {
            "typePath": "item:product:footwear",
            "identifier": "{projectIdentifier}:footwear:global.assortment"
          }
        }
      ]
    }
  ]
}'

The expected body of the POST is the ProjectConfiguration shape described above.

CLI Usage

The CLI has one command to load/update a project:

contrail projects load <File Paths>

This YAML file is used to set up the configuration for loading projects.

projectConfiguration:
  projectName: "{projectName}"
  identifier: "{projectIdentifier}"
  commonConfig:
    projectIdentifier: PROJECT_IDENTIFIER
    projectName: PROJECT_NAME
  subFolders:
  - name: Apparel
    identifier: "{projectIdentifier}:apparel.folder"
    assortments:
    - identifier: "{projectIdentifier}:apparel:global.plan"
      name: "{projectName} Apparel Global"
      type: PLAN
      assortmentAtts:
        typePath: item:product:apparel
        identifier: "{projectIdentifier}:apparel:global.assortment"
  - name: Accessories
    identifier: "{projectIdentifier}:accessories.folder"
    assortments:
    - identifier: "{projectIdentifier}:accessories:global.plan"
      name: "{projectName} Accessories Global"
      type: PLAN
      assortmentAtts:
        typePath: item:product:accessories
        identifier: "{projectIdentifier}:apparel:global.assortment"
  - name: Equipment
    identifier: "{projectIdentifier}:equipment.folder"
    assortments:
    - identifier: "{projectIdentifier}:equipment:global.plan"
      name: "{projectName} Equipment Global"
      type: PLAN
      assortmentAtts:
        typePath: item:product:equipment
        identifier: "{projectIdentifier}:equipment:global.assortment"
  - name: Footwear
    identifier: "{projectIdentifier}:footwear.folder"
    assortments:
    - identifier: "{projectIdentifier}:footwear:global.plan"
      name: "{projectName} Footwear Global"
      type: PLAN
      assortmentAtts:
        typePath: item:product:footwear
        identifier: "{projectIdentifier}:footwear:global.assortment"