Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] API Guide for Front-End Developers #44

Open
shaunanoordin opened this issue Aug 2, 2017 · 1 comment
Open

[WIP] API Guide for Front-End Developers #44

shaunanoordin opened this issue Aug 2, 2017 · 1 comment

Comments

@shaunanoordin
Copy link
Member

shaunanoordin commented Aug 2, 2017

Zooniverse Education API

A front-end dev's reverse-engineering of the Zoo EduAPI endpoints, as used by WildCam (Gorongosa) Lab.

This is only a WIP and will be turned into a proper README-like guide/API documentation once completed.

Please feel free to edit/contribute/correct, especially if you know more about the eldritch magicks of Ruby and can simply read the repo code.

Basic Setup

The Education API follows the standard JSON API 1.0 rules. API requests need to have some Zooniverse/Panoptes authorisation code in their request headers - fortunately, this is easily done using the Panoptes JavaScript client.

Example code, using fetch():

import apiClient from 'panoptes-client/lib/api-client';
import fetch from 'isomorphic-fetch';  //The isomorphic-fetch library will save you headaches when handling IE11. Or use a non-fetch alternative.

fetch(root + assignments, {
  method: 'POST',
  mode: 'cors',
  headers: new Headers({
    'Authorization': apiClient.headers.Authorization,  //Get your Auth code
    'Content-Type': 'application/json'
  }), 
  body: JSON.stringify({  //REMINDER: Transform into a string!
    "data": {
      "attributes": { "name": "TEST" }
    }
  })
})
.then(response => response.json())
.then(json => { ...(yadda yadda)... });

Example Request header will look like...

POST /teachers/classrooms/ HTTP/1.1
Host: education-api.zooniverse.org
Connection: keep-alive
Content-Length: 81
Pragma: no-cache
Cache-Control: no-cache
User-Agent: ...(yadda yadda)...
Origin: http://localhost:3000
authorization: ...(yadda yadda)...
content-type: application/json
Accept: */*
Referer: http://localhost:3000/teachers/classrooms/new
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.8

WARNING (2017.08.07)

While this document was being written, we had a bit of a quirk where certain item key names use - dashes instead of the intended _ underscores.

For example, you might see some Response bodies replying with join-token instead of join_token - join_token is the correct one. Please adjust your code accordingly once this quirk has been fixed.

Programs

A program is a database representation of a curricula associated with a Zooniverse project or many projects. Generally, there are two "types" of programs: Wildcam style and Intro2Astro style. The type is indicated by the custom boolean property on the program resource.

Wildcam style programs have custom: true set, meaning:

  • Assignments are created by teachers
  • Assignments on POST, the API:
    • clones the workflow id given in the payload
    • creates a new subject set with the subject ids in the payload
    • links the new subject set to the new workflow
    • assigns student users to the assignment
  • Does some Carto DB stuff (TO DO: what Carto DB stuff?)

Intro2Astro style programs have custom: false set, meaning:

  • Assignments are "auto"-created on the classroom POST
    • This is done by the front end client via javascript
    • How to create the assignments are stored arbitrarily in the program's metadata object
    • Students when joining the classroom get automatically assigned to the assignments

Classrooms and Programs relationship

  • Linked to a program on POST
  • Filtered by program id on GET

GET programs

Request

GET https://education-api.zooniverse.org/programs

Response (Success)

200 OK

Body:

{
  "data": [
    {
      "id": "1",
      "type": "programs",
      "attributes": {
        "slug": "astro-101-with-galaxy-zoo",
        "name": "Astro 101 with Galaxy Zoo",
        "metadata": {
          "cardImage": "home-card-intro-to-astro.jpg",
          "assignments": {
            "2218": {
              "name": "Hubble's Law",
              "slug": "srallen086/intro2astro-hubble-testing",
              "classifications_target": "10"
            },
            "3037": {
              "name": "Galaxy Zoo 101",
              "slug": "srallen086/galaxy-zoo-in-astronomy-101",
              "classifications_target": "22"
              }
            },
            "redirectOnJoin": false,
            "backgroundImage": "astro-background.jpg"
          },
        "description": "Materials and tools for engaging introductory astronomy students in real research with Galaxy Zoo.",
        "custom": false
      }
    }, 
    {
      "id": "2",
      "type": "programs",
      "attributes": {
        "slug": "wildcam-darien-lab",
        "name": "Wildcam Darien Lab",
        "metadata": {
          "cardImage": "home-card-wildcam-darien.jpg",
          "workflowId": "3116",
          "redirectOnJoin":true,
          "sampleSubjects": ["73437","73438","73434"],
          "backgroundImage": ""
        },
        "description": "A map for exploring camera trap data from the WildCam Darien project.",
        "custom": true
      }
    }, {
      "id": "4",
      "type": "programs",
      "attributes": {
        "slug": "wildcam-gorongosa-lab",
        "name": "Wildcam Gorongosa Lab",
        "metadata": {
          "redirect": "https://lab.wildcamgorongosa.org/",
          "cardImage": "gorongosa-animals.jpg",
          "workflowId": "1549",
          "sampleSubjects": ["37763","37755","37767"]
        },
        "description": "A map for exploring camera trap data from the WildCam Gorongosa project.",
        "custom": true
      }
    }
  ]
}

The API currently does not support other CRUD actions yet for programs. If a new program needs to be created or a program needs updating, then it'll have to be done via the Rails console.

Teacher Stuff

A Teacher needs to do the following:

  • Create and manage Classrooms.
    • Each Classroom:
      • Has its own metadata. (Name, description, etc)
      • Has any number of Students.
      • Has any number of Assignments (if Wildcam style program).
      • Linked to a Program
      • Filtered by a Program
  • Create and manage Assignments within Classrooms if the classroom is linked to a Wildcam style program.
    • Each Assignment:
      • Is... basically a Zooniverse workflow? (TBC)
      • Is... associated with a Zooniverse workflow id? (TBC)
      • Is associated with a Classroom.
      • Has its own metadata. (Name, description, etc)
      • Has any number of Subject ids. (If linked to a Wildcam style program. Used to create the workflow. How Subject ids are selected... now that's the fun part!)
      • Has any number of Students. (Must be a subset of Students in the Classroom)

Get Classrooms

Request

GET https://education-api.zooniverse.org/teachers/classrooms/?program_id=1

Response (Success)

200 OK

Body:

{
  "data": [
    {
      "id": "1265",
      "type": "classrooms",
      "attributes": {
        "name": "Zoo Class",
        "join-token": "6b051b8be8c8e57c",
        "school": "Zootown",
        "subject": "Zooniverse classroom",
        "description": "A sample classrom",
        "classifications-count": 0
      },
      "relationships": {
        "groups": {
          "data": []
        },
        "students": {
          "data": [
            {
              "id": "4247",
              "type": "student-users"
            },
            {
              "id": "4245",
              "type": "student-users"
            },
            {
              "id": "4246",
              "type": "student-users"
            }
          ]
        }
      }
    }
  ],
  "included": [
    {
      "id": "4247",
      "type": "student-users",
      "attributes": {
        "zooniverse-id": "1459736",
        "zooniverse-login": "zootester3",
        "zooniverse-display-name": "zootester3",
        "classifications-count": 0
      }
    },
    {
      "id": "4245",
      "type": "student-users",
      "attributes": {
        "zooniverse-id": "1459668",
        "zooniverse-login": "zootester1",
        "zooniverse-display-name": "zootester1",
        "classifications-count": 0
      }
    },
    {
      "id": "4246",
      "type": "student-users",
      "attributes": {
        "zooniverse-id": "1459734",
        "zooniverse-login": "zootester2",
        "zooniverse-display-name": "zootester2",
        "classifications-count": 0
      }
    }
  ]
}

Create Classroom

Request

POST https://education-api.zooniverse.org/teachers/classrooms/

Body:

{
  "data": {
    "attributes": {
      "name": "Zoo Class",
      "subject": "Zooniverse classroom",  //Optional
      "school": "Zootown",  //Optional
      "description": "A sample classrom"  //Optional
    },
    relationships: {
      program: {
        data: {
          id: '1',
          type: 'programs'
        }
      }
    }
  }
}

Response (Success)

201 Created

Body:

{
  "data": {
    "id": "1265",
    "type": "classrooms",
    "attributes": {
      "name": "Zoo Class",
      "join-token": "6b051b8be8c8e57c",
      "school":"Zootown",
      "subject":
      "Zooniverse classroom",
      "description": "A sample classrom",
      "classifications-count": 0
    },
    "relationships": {
      "groups": {
        "data": []
      },
      "program": {
        "data": { 
          "id": "1",
          type: "programs"
        }
      },
      "students": {
        "data": []
      }
    }
  }
}

Edit Classroom

Request

PUT https://education-api.zooniverse.org/teachers/classrooms/1265

Body:

{
  "data": {
    "attributes": {
      "name": "Zoo Class???",
      "subject": "Zooniverse classroom...",
      "school": "Zootown!!!",
      "description": "A sample classrom..."
    }
  }
}

Response (Success)

204 No Content

Delete Classroom

Request

DELETE https://education-api.zooniverse.org/teachers/classrooms/1288

Response (Success)

204 No Content

Delete Student from Classrom

Request

DELETE https://education-api.zooniverse.org/teachers/classrooms/1265/student_users/4246

Response (Success)

204 No Content

Get Assignments

Request

https://education-api.zooniverse.org/assignments?classroom_id=365

Body:

{
  "data": [
    {
      "id": "303",
      "type": "assignments",
      "attributes": {
        "name": "Hubble's Law",
        "metadata": {
          "classifications_target": "10"
        },
        "classroom_id": 365,
        "workflow_id": "2218",
        "subject_set_id": null
      },
      "relationships": {
        "student_assignments": {
          "data": [
            {
              "id": "250",
              "type": "student_assignments"
            },
            {
              "id": "252",
              "type": "student_assignments"
            }
          ]
        },
        "student_users": {
          "data": [
            {
              "id": "306",
              "type": "student_users"
            },
            {
              "id": "307",
              "type": "student_users"
            }
          ]
        }
      }
    }
  ],
  "included": [
    {
      "id": "249",
      "type": "student_assignments",
      "attributes": {
        "student_user_id": 306,
        "classifications_count": 0
      }
    },
    {
      "id": "251",
      "type": "student_assignments",
      "attributes": {
        "student_user_id": 307,
        "classifications_count": 0
      }
    }
  ]
}

Create Assignment

Request

Body:

{
  "data": {
    "attributes": {
      "name": "Galaxy Zoo 101",
      "metadata": {
        "classifications_target": "22"
      },
      "workflow_id": "3037"
    },
    "relationships": {
      "classroom": {
        "data": {
          "id": "376",
          "type": "classrooms"
        }
      }
    }
  }
}

Response

201 Created

{
  "data": {
    "id": "318",
    "type": "assignments",
    "attributes": {
      "name": "Galaxy Zoo 101",
      "metadata": {
        "classifications_target": "22"
      },
      "classroom_id": 376,
      "workflow_id": "3037",
      "subject_set_id": null
    },
    "relationships": {
      "student_assignments": {
        "data": []
      },
      "student_users": {
        "data": []
      }
    }
  }
}

Edit Assignment

TBD

Delete Assignment

TBD

Student Stuff

Join Classroom

Request

POST https://education-api.zooniverse.org/students/classrooms/1265/join

Body:

{
  "join_token": "6b051b8be8c8e57c"
}

Response (Success)

201 Created

Body:

{
  "data": {
    "id": "1265",
    "type": "classrooms",
    "attributes": {
      "name": "Zoo Class",
      "join-token":"6b051b8be8c8e57c",
      "school": "Zootown",
      "subject": "Zooniverse classroom",
      "description": "A sample classrom",
      "classifications-count": 0
    },
    "relationships": {
      "groups": {
        "data": []
      },
      "students": {
        "data": [
          {"id": "4247", "type": "student-users"},
          {"id": "4245", "type": "student-users"},
          {"id": "4248", "type": "student-users"}
        ]
      }
    }
  },
  "included":[
    {
      "id": "4247",
      "type": "student-users",
      "attributes": {
        "zooniverse-id": "1459736",
        "zooniverse-login": "zootester3",
        "zooniverse-display-name": "zootester3",
        "classifications-count": 0
      }
    },
    {
      "id": "4245",
      "type": "student-users",
      "attributes": {
        "zooniverse-id": "1459668",
        "zooniverse-login": "zootester1",
        "zooniverse-display-name": "zootester1",
        "classifications-count": 0
      }
    },
    {
      "id": "4248",
      "type": "student-users",
      "attributes": {
        "zooniverse-id": "1475095",
        "zooniverse-login": "zootester4",
        "zooniverse-display-name": "zootester4",
        "classifications-count": 0
      }
    }
  ]
}

Response (Error - Already Joined)

422 Unprocessable Entity

Body:

{
  "errors": [
    {
      "status": 422,
      "source": {
        "pointer": "/data/attributes/id"
      },
      "detail": "cannot join"
    }
  ]
}

Response (Error - Can't Find Classroom / Invalid Join Token(?))

404 Not Found

Body: a 404 page

Get Assignments

TBD

@srallen
Copy link
Contributor

srallen commented Dec 5, 2017

I've updated to include the programs resource, and updated the classroom and assignment examples per the updates to the API.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants