Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 2 Current »

Introduction

Sunbird platform enabled the contributors to create the content & once reviewers review that content and approved it is available for consumption.

This wiki explains the design of the content contribution and review lifecycle.

Background & Problem statement:

We have enabled the content contribution under a project. Any contributor contributes the content only through the project & he/she can’t reuse the same content for multiple projects. Contribution related information currently, we are storing at the content level & this is not a scalable solution.

Currently, We have two levels of reviewers - contribution org reviewers and sourcing org reviewers and this is hardcoded in the code level. If we want to introduce a new review process we need to do again code changes to support & this is not a scalable solution.

Key Design Problems:

  1. Define contribution lifecycle & enable API’s

  2. Enable multi-level review process for contribution.

Design:

As of now, we are storing all the contribution and review information at the content level. Going forward we will split the information into the individual objects as

Content vs Contribution vs ReviewObject metadata:

Content - Properties

Contribution - Properties

Review Object - Properties

name

CB:UUID

RO:UUID

status (at content level)

name

contributionId

artifactUrl

contentId

reviewerId

previewUrl

collectionId

status (by this reviewer)

downloadUrl

unitid

reviewerName

programId

publishComments

many more…

userId

rejectComments

userName

requestChanges

index

many more…

Lifecycle management:

When we create a content object, at the time the contribution object will also be created. We will not maintain any status at the contribution object level. Review object will be created when the content is submitted for review. From there review lifecycle will be dependent on the reviewer. Below is the lifecycle of the review objects. We can have multiple levels of reviews for a given content/contribution object.

The following image explains the weightage/score of statuses.

  • Approved is 1

  • Submitted is 2

  • Request Changes is 3

  • Rejected is 4

Ex-1: If the content is being reviewed parallelly it will have two review objects. Let's say one of the review objects is having the status Approved and another one has Rejected. Now the Rejected status outweighs the Approved status. Hence the content's actual status becomes Rejected.

Ex-2: Content again having two review status Approved and RequestChanges. RequestChanges will take precedence.

API Spec:

Content Create wrapper API:

Method: POST
Path: https://dock.sunbirded.org/api/program/v1/contribution/create

Request Payload:

{
    "request": {
        "contribution": {
          "programId": "",
          "collectionId": "",
          "unitId": "",
          "name": "",
          "userName": "",
          "userId": ""
        },
        "content": {
          "name": "",
          "mimeType": "",
          "primaryCategory": "",
          "contentType": "",
          "creator": "",
          "createdBy": ""
        }
    }
}

Response Payload:

{
    "id": "api.contribution.create",
    "ver": "3.0",
    "ts": "2021-02-24T06:50:03ZZ",
    "params": {
        "resmsgid": "64b393de-a9e1-4857-97e4-7caf270b4cfc",
        "msgid": null,
        "err": null,
        "status": "successful",
        "errmsg": null
    },
    "responseCode": "OK",
    "result": {
        "content": {
          "identifier": "do_1132231119107358721191",
          "versionKey": "1614150204576"
        },
        "contribution": {
          "identifier": "CO:1132231119107358721191"
        }
    }
}

Content Create wrapper API:

Method: POST
Path: https://dock.sunbirded.org/api/program/v1/contribution/update

Request Payload:

{
    "request": {
        "content": {
          "name": "",
          "versionKey": "1612319891349"
        },
        "contribution": {
          "contentId": "",
          "collectionId": "",
          "programId": "",
          "userId": ""
        },
        "review": {
          "contributionId": "CO:2222222222222",
          "status": "Approved", // Approved, Rejected, RequestChanges and submited
          "publishComments": "",
          "reviewerName": "",
          "reviewerId": ""
        }
    }
}

Response Payload:

{
    "id": "api.contribution.update",
    "ver": "3.0",
    "ts": "2021-02-24T07:03:24ZZ",
    "params": {
        "resmsgid": "e7721609-4b75-4358-b0ff-eeac0d8f3f7a",
        "msgid": null,
        "err": null,
        "status": "successful",
        "errmsg": null
    },
    "responseCode": "OK",
    "result": {
        "content": {
          "identifier": "do_1132231119107358721191",
          "versionKey": "1614150204576"
        },
        "contribution": {
          "identifier": "CO:1132231119107358721191"
        },
        "review": {
          "identifier": "RO:1132231119107358721191"
        }
    }
}
Content review wrapper API:

Method: POST
Path: https://dock.sunbirded.org/api/program/v1/contribution/review

Request Payload:

{
    "request": {
        "review": {
          "contentId": "",
          "collectionId": "",
          "programId": ""
        }
    }
}

Response Payload:

{
    "id": "api.contribution.review",
    "ver": "3.0",
    "ts": "2021-02-24T07:03:24ZZ",
    "params": {
        "resmsgid": "e7721609-4b75-4358-b0ff-eeac0d8f3f7a",
        "msgid": null,
        "err": null,
        "status": "successful",
        "errmsg": null
    },
    "responseCode": "OK",
    "result": {
        "content": {
          "identifier": "do_1132231119107358721191",
          "versionKey": "1614150204576"
        },
        "review": {
          "identifier": "RO:1132231119107358721191"
        }
    }
}
Content publish wrapper API:

Method: POST
Path: https://dock.sunbirded.org/api/program/v1/contribution/publish

Request Payload:

{
    "request": {
        "review": {
          "contentId": "",
          "collectionId": "",
          "programId": ""
        }
    }
}

Response Payload:

{
    "id": "api.contribution.publish",
    "ver": "3.0",
    "ts": "2021-02-24T07:03:24ZZ",
    "params": {
        "resmsgid": "e7721609-4b75-4358-b0ff-eeac0d8f3f7a",
        "msgid": null,
        "err": null,
        "status": "successful",
        "errmsg": null
    },
    "responseCode": "OK",
    "result": {
        "content": {
          "identifier": "do_1132231119107358721191",
          "publishStatus": "Publish Operation for Content Id 'do_1132224396322734081169' Started Successfully!",
        },
        "review": {
          "identifier": "RO:1132231119107358721191"
        }
    }
}
Content list wrapper API:

Method: POST
Path: https://dock.sunbirded.org/api/program/v1/contribution/list

Request Payload:

{
    "request": {
        "review": {
          "collectionId": "",
          "programId": ""
        }
    }
}

Response Payload:

{
  "id": "api.contribution.list",
  "ver": "3.0",
  "ts": "2021-02-24T15:26:10ZZ",
  "params": {
    "resmsgid": "962d09e6-91ef-4630-b546-a9529f349921",
    "msgid": null,
    "err": null,
    "status": "successful",
    "errmsg": null
  },
  "responseCode": "OK",
  "result": {
    "count": 2,
    "contribution": [
      {
        "content": {
          "name": "",
          "creator": "",
          "createdBy": ""
        },
        "contribution": {
          "name": "",
          "collectionId": "",
          "programId": "",
          "unitId": ""
        },
        "review": [
          {
            "contributionId": "CO:11111",
            "status": "Approved",
            "publishComments": "",
            "reviewerName": "",
            "reviewerId": ""
          },
          {
            "contributionId": "CO:2222",
            "status": "Approved",
            "publishComments": "",
            "reviewerName": "",
            "reviewerId": ""
          }
        ]
      },
      {
        "content": {},
        "contribution": {},
        "review": [
          {},
          {}
        ]
      }
    ]
  }
}

Conclusion:

<TODO>


  • No labels