Giter VIP home page Giter VIP logo

teacher-workout-backend's Introduction

Teacher Workout

GitHub contributors GitHub last commit License: MPL 2.0

Check out the Wiki!

Teacher Workout was prototyped in Civic Labs, the research and prototyping program in Code for Romania.

Teacher Workout is an application meant to deliver shot, interactive lessons. The themes of these lessons include identifying children who manifest a difficulty in learning, handling difficult classrooms situations, integrating children with particular needs in a classroom. These micro-courses are meant to help foster positive habits for teachers and professors alike.

The Teacher Workout ecosystem is composed of:

The Teacher Workout prototype and UI is available in the Figma project.

Contributing | Built with | Repos and projects | Deployment | Feedback | License | About Code4Ro

Contributing

This project is built by amazing volunteers and you can be one of them! Here's a list of ways in which you can contribute to this project. If you want to make any change to this repository, please make a fork first.

Help us out by testing this project in the staging environment. You can use a GraphQL client like Insomnia. If you see something that doesn't quite work the way you expect it to, open an Issue. Make sure to describe what you expect to happen and what is actually happening in detail.

If you would like to suggest new functionality, open an Issue and mark it as a [Feature request]. Please be specific about why you think this functionality will be of use. If you can, please include some visual description of what you would like the UI to look like, if you are suggesting new UI elements.

Built With

  • love
  • grahpql

Programming languages

  • c#
  • kotlin
  • swift
  • js

Platforms

  • native mobile android and ios

Frontend framework

  • react

Package managers

  • npm

Database technology & provider

  • postgres

API endpoints

  • GraphiQL (available at /ui/graphiql)

Repos and projects

Set Up

Install Dependencies

  • docker-compose >= v1.26.2
  • docker >= v20.10.7

Start DB server

cp .env.example .env
docker-compose up # and stop
docker start teacher_workout_db

TODO: decouple docker-compose in development from staging

Run migrations

dotnet ef database update --startup-project TeacherWorkout.Api/ --project TeacherWorkout.Data/

Start App

dotnet run -p TeacherWorkout.Api

FAQ

Add a migration

dotnet ef migrations add <MigrationNameGoesHere> --startup-project TeacherWorkout.Api/ --project TeacherWorkout.Data/

Run tests

ASPNETCORE_ENVIRONMENT=Test dotnet test

Apply migrations and seed data to your dev DB

Migrations will be applyed using the Migrator in all environments when running the application with docker.

If dummy data is needed for development purposes just set the SEEDDATA to true in the .env file when runngin locally using docker. This will populate the DB with some dummy data on the first run. Subsequent runs will not re-seed if the data is already present.

SEEDDATA=true

Alternatively, you can run the following commands to only run the Migrator in your local environment as needed.

cd TeacherWorkout.Migrator
dotnet run SeedData=false

Deployment

Guide users through getting your code up and running on their own system. In this section you can talk about:

  1. Installation process
  2. Software dependencies
  3. Latest releases
  4. API references

Describe and show how to build your code and run the tests.

Feedback

  • Request a new feature on GitHub.
  • Vote for popular feature requests.
  • File a bug in GitHub Issues.
  • Email us with other feedback [email protected]

License

This project is licensed under the MPL 2.0 License - see the LICENSE file for details

About Code for Romania

Started in 2016, Code for Romania is a civic tech NGO, official member of the Code for All network. We have a community of around 2.000 volunteers (developers, ux/ui, communications, data scientists, graphic designers, devops, it security and more) who work pro-bono for developing digital solutions to solve social problems. #techforsocialgood. If you want to learn more details about our projects visit our site or if you want to talk to one of our staff members, please e-mail us at [email protected].

Last, but not least, we rely on donations to ensure the infrastructure, logistics and management of our community that is widely spread across 11 timezones, coding for social change to make Romania and the world a better place. If you want to support us, you can do it here.

teacher-workout-backend's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

teacher-workout-backend's Issues

Configure database

We will use PostgreSQL. Configure EntityFramework to use PostgreSQL.
We need a way to configure the env (consider .env or similar).

  • Add an example of the config
  • Update Readme to reference the example config.

Filter lessons by term

Update the query "lessons" to accept an optional "term" argument.

If provided we need to return only lessons that match that term on the lesson "title"

Add support for tests

We need a project where we can write tests against the API.

We need to support:

  • unit tests
  • integration tests

Setup GraphQL schema

We need to define the classes for the GraphQL types.

schema {
    query: Query
    mutation: Mutation
}

"An object with an ID."
interface Node {
    "ID of the object."
    id: ID!
}

type Query {
    themes(
        "Returns a list of themes"
        after: String,
        "Returns the elements in the list that come before the specified cursor."
        before: String,
        "Returns the first _n_ elements from the list."
        first: Int,
        "Returns the last _n_ elements from the list."
        last: Int
    ): ThemeConnection!

    lessons(
        "Filter by the theme id. If missing, we return all lessons"
        themeId: ID,

        "Returns a list of themes"
        after: String,
        "Returns the elements in the list that come before the specified cursor."
        before: String,
        "Returns the first _n_ elements from the list."
        first: Int,
        "Returns the last _n_ elements from the list."
        last: Int
    ): LessonConnection!

    step(
        "Filter by the theme id. If missing, we return all lessons"
        stepId: ID!
    ): StepUnion!
}

type Mutation {
    lessonSave(input: LessonSaveInput!): LessonSavePayload

    "Used to complete a SlideStep and an ExerciseSummaryStep"
    stepComplete(input: StepCompleteInput!): StepCompletePayload

    "Used to complete a ExerciseStep"
    stepSubmitAnswer(input: StepSubmitAnswerInput!): StepSubmitAnswerPayload
}

# QUERY ==================================================
"The connection type for Theme."
type ThemeConnection {
    "Amount of records for this edge"
    count: Int!
    "A list of edges."
    edges: [ThemeEdge]
    "A list of nodes."
    nodes: [Theme]
    "Information to aid in pagination."
    pageInfo: PageInfo!
}

"The connection type for Theme."
type LessonConnection {
    "Amount of records for this edge"
    count: Int!
    "A list of edges."
    edges: [LessonEdge]
    "A list of nodes."
    nodes: [Lesson]
    "Information to aid in pagination."
    pageInfo: PageInfo!
}

"Information about pagination in a connection."
type PageInfo {
    "When paginating forwards, the cursor to continue."
    endCursor: String
    "When paginating forwards, are there more items?"
    hasNextPage: Boolean!
    "When paginating backwards, are there more items?"
    hasPreviousPage: Boolean!
    "When paginating backwards, the cursor to continue."
    startCursor: String
}

"An edge in a connection."
type ThemeEdge {
    "A cursor for use in pagination."
    cursor: String!
    "The item at the end of the edge."
    node: Theme
}

"An edge in a connection."
type LessonEdge {
    "A cursor for use in pagination."
    cursor: String!
    "The item at the end of the edge."
    node: Lesson
}

# INPUTS ================================================

input LessonSaveInput {
    lessonId: ID!
}

input StepCompleteInput {
    stepId: ID!
}

input StepSubmitAnswerInput {
    stepId: ID!
    answerIds: [ID!]
}

# TYPES ================================================

"A grouping of Lessons"
type Theme implements Node {
    id: ID!
    title: String!
    thumbnail: Image!
}

type Image {
    description: String!
    url: String!
}

enum DurationUnit {
    HOURS
    MINUTES
}

type Duration {
    value: Int!
    unit: DurationUnit!
    displayValue: String!
}

type Lesson implements Node {
    id: ID!
    title: String!
    thumbnail: Image!
    theme: Theme!
    duration: Duration!
}

# TODO: Decide to have LessonStatus exported as a Separate Query or extend the Lessson Type

type LessonStatus {
    percentComplete: Int!
    currentStep: StepUnion!
}

type LessonSavePayload {
    lesson: Lesson!
}

type StepCompletePayload {
    step: StepUnion!
    lesonStatus: LessonStatus!
}

type StepSubmitAnswerPayload {
    step: StepUnion!
    lesonStatus: LessonStatus!
}

interface LessonStep {
    "ID of the object."
    id: ID!
}

enum AnswerStatus {
    CORRECT
    INCORRECT
    NONE
}

type AnswerResult {
    answer: Answer!
    status: AnswerStatus!
}

type SlideStep implements LessonStep {
    id: ID!
    title: String!
    previousStep: StepUnion

    image: Image
    description: String!
}

type ExerciseStep implements LessonStep {
    id: ID!
    title: String!

    question: String!
    answers: [Answer]
}

type Answer {
    id: ID!
    title: String!
}

type LessonSummaryStep implements LessonStep {
    id: ID!

    experiencePoints: Int!
}

type ExerciseSummaryStep implements LessonStep {
    id: ID!

    results: [AnswerResult!]
}

union StepUnion = SlideStep | ExerciseStep | ExerciseSummaryStep | LessonSummaryStep

Decide on how we expose LessonStatus

We need to expose the progress for lessons to clients so they can display progress bars:

  • while on the lesson page
  • while on the lesson list page

LessonStatus:

type LessonStatus {
    percentComplete: Int!
    currentStep: StepUnion!
}

Options:

  1. Export LessonStatus as a Separate Query node
    Pros:
    Facilitates caching
    Decoupling so that an issue on the statuses will not limit users from browsing lessons

  2. Extend the Lesson Type with a "status" field
    Pros:
    Less client work to match the Status with the Lesson

Pros for 2) are Cons for 1) and vice-versa.

Add lessons connection to the theme type

We need to be able to get the total count of lessons associated with a theme to be displayed on the Theme List admin page

For this, we can add a Lesson Connection to the ThemeType.

Filter lessons by status

Update the query "lessons" to accept an optional "status" argument.

Possible values:

  • Draft
  • Published

We need to add the column to the actual lesson.

Implement lessonStatuses query

Implement ILessonStatusRepository in TeacherWorkout.Data
Add Model to the DbContext.

Define a "User" model.
Link LessonStatus to a User + LessonStep.

Implement cursor based pagination

We want to support cursor based pagination for Lessons. We already receive the parameters and pass them through all the way to the repository.

Remove outdated dependency that holds back GraphQL to an old version

Is your feature request related to a problem? Please describe.
The upload library mentioned in #57 cannot be integrated, because GraphQL is at 4.6.1

Describe the solution you'd like
Remove GraphQL.Server.Transports.AspNetCore.SystemTextJson dependency that holds back updating to GraphQL 7.
Migrate code to use the new GraphQL version.

Describe alternatives you've considered
None

Additional context
GraphQL at 4.6.1 (project.assets.json):
Screenshot 2023-11-28 at 12 56 42

Migration notice from GraphQL NuGet:
Screenshot 2023-11-28 at 13 10 17

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.