Git Product home page Git Product logo

api-volontaria's People

Contributors

francisjeanneau avatar pyup-bot avatar rignonnoel avatar sylvaus avatar vardane avatar willkoua avatar yanicolivier avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

api-volontaria's Issues

Travis coding style check

Expected behaviour

Travis should be checking the coding style too, ie: ending comma in a list or dict

Current behavior

Travis is currently checking syntax according to the PEP8 styleguide.

Potential solution

We should make a personalized style check in Travis' file

  • Use the flake8-commas module to lint trailing commas.
  • Refer to this blog post where flake8 and pylint are used together.

User POST password validation failure

Expected behaviour

When POSTing a new user, I expect the API to store the password correctly.

Current behavior

When testing with the live API view at /documentation, if you POST a new user, the API fails to store the password correctly in the database.

Potential solution

Add a step in the User serializer in the create() override to validate the password.
ex:

user.set_password(**validated_data['password'])

Step to reproduce (if it's a bug)

  1. Setup the API locally and ./manage.py runserver
  2. Navigate to localhost:8000/documentation
  3. Click on the /user endpoint and then the electrical plug
  4. Click "POST", fill the data and click send.
  5. After the successfully creating the user, visit localhost:8000/admin and check the new user.

You should see this in the password field:
image

Your environment (if it's a bugs)

  • Version used : Develop branch
  • Version of softwares (python, firefox, chrome, ..) : Python 3.6.2, Chrome Version 60.0.3112.90 (Build officiel) (64 bits)
  • Operating System (Windows, Mac, Ubuntu, ArchLinux, ..): ArchLinux

Allow users to change password if they forgot their own

Expected behaviour

I want to have an endpoint to change my forgotten password.

Current behavior

If i forgot my password i need to contact an administrator of the instance.

Potential solution

First step
I call the endpoint (without authentication) and give my username in the body.

Second step
1 - If a link is specified in the settings : A token is generated by the API and i receive an email with a link (who contain the token) to change my password.

2 - If email are not configured in settings : The endpoint return an error and ask me to contact an administrator.

Third step
I call a second endpoint (without authentication) with the token and a password in the body.

Fix format of email attributs

Expected behavior

All email attributs are in caps, without special characters, without space

ex: ACTIVATIONURL

Current behavior

Format are not valid for SendInBlue

ex: activation_url

Potential solution

Just change the format

Finish and document the new diagram of data

Expected behaviour

We want to have the first finalized diagram of data to defined the scope of the project.

Current behavior

It's a new part of the project, so we don't have a current behavior

Potential solution

  • Use PlantText to generate the documentation from text
  • Store this content in a new directory documentation on the root of the repository

Sync of migrations

Expected behaviour

When i make a makemigrations from the develop branch, i've no one change.

Current behavior

When i make a makemigrations from the develop branch, i've this:

Migrations for 'apiVolontaria':
  source/apiVolontaria/apiVolontaria/migrations/0004_auto_20171224_1736.py
    - Alter field created on activationtoken
Migrations for 'location':
  source/apiVolontaria/location/migrations/0002_auto_20171224_1736.py
    - Alter unique_together for country (0 constraint(s))
    - Alter unique_together for stateprovince (0 constraint(s))

Potential solution

  1. Make a PR to fix this result
  2. Implement a test to check the makemigrations doesn't return new migrations file on TravisCI

Step to reproduce (if it's a bug)

  1. Pull the develop branch
  2. Call the makemigrations command : python source/apiGiggle/manage.py makemigrations
  3. Check the result

Your environment (if it's a bugs)

  • Version used : Develop (commit : c2cd8d19ad4e0d196ac22b33fcb2b6b9576adba2)
  • Version of softwares (python, firefox, chrome, ..) : Python 3.6.3
  • Operating System (Windows, Mac, Ubuntu, ArchLinux, ..): Arch Linux

Auto-generate code's documentation

Expected behaviour

We need a way to auto-generate our code's documentation

Current behavior

No documentation is auto-generated (except the API endpoints with swagger)

Potential solution

We could use Sphinx and be able to upload our docs to readthedocs and/or github.

First prototype of user interface

Expected behaviour

We have a first prototype of user interface in HTML and CSS

  • Each page are made (see actual instance of Chapie)
  • CSS transiton are made (button, link, hover on list, etc..)
  • The prototype is based on the new architecture of SCSS (issues #6)

Current behavior

We don't have a prototype for the moment

Potential solution

  • Just reproduce the same visual as chapie for the moment
  • Take care to only use variable for ALL color
  • Take care to only use variable for ALL transition
  • Do not hesitate to populate HTML render with some data to have a visual

Views permission check is wrong for objects update

Expected behaviour

The views should check for the correct permissions.

Current behavior

Currently, in the case of an update request to an object, the view checks if the user has the permission update_model. However, the default Django permission created for models is change_model.

Potential solution

We need to fix this by changing update_***** permissions by change_*****

Create test script

Expected behaviour

We want to have a script we can launch to test all the repository like Travis before create our PR.

  • Styling
  • Coverage
  • Tests
  • ...

Current behavior

Actually i need to test all by myself or create a new PR to let Travis do the work (so i need to wait to see a little typo in PEP8...)

Potential solution

Create a test script so user can easily and rapidly check their code before submit a new PR.

Migrations problem on TemporaryToken

Expected behaviour

We we run makemigrations command, we want to have only new modification and not a list of default field who change in function of time and spam the migrations system

Current behavior

Actually, when we run the makemigrations command we have ALWAYS a new migrations from theTemporaryToken model.

Potential solution

Change the way we put the default value to not change each time we create a new migration.

A potential solution (maybe not the best, i don't know) is to overwrite the save() method of the model class to change the default value. This way we migrations system will be not impacted.

class TemporaryToken(Token):
    """Subclass of Token to add an expiration time."""
    expires = models.DateTimeField(
        default=timezone.now() + timezone.timedelta(
            minutes=settings.REST_FRAMEWORK_TEMPORARY_TOKENS['MINUTES']
        )
)

Step to reproduce (if it's a bug)

  1. run python source/apiVolontaria/manage.py makemigrations
  2. check the migration folder of the apiVolontaria application.
  3. a new migration has been created only to change the default value with new value of time

Your environment (if it's a bugs)

  • Version used : Develop version
  • Version of softwares (python, firefox, chrome, ..) : Python 3.6.2
  • Operating System (Windows, Mac, Ubuntu, ArchLinux, ..): ArchLinux

Local settings

Expected behaviour

We want to have a way to edit just some variable of the local_settings without have conflitcs

Current behavior

We can just edit the real settings file of the project

Potential solution

Create a local_settings file who overwrite only some options and let other options at default value of the repository.

Make the header of the promotionnal website more responsive

Expected behaviour

  • I want to have github and documentation button centered in the header when i visit the page with my smartphone.

  • I want to have a blue space all around the Volontaria white box on the top of the page.

Current behavior

  • Buttons are aligned on the right, which is good when i'm on my laptop, but not when i'm on my smartphone.

  • Big white box is correctly display on laptop but is truncated when i visit the page with my smartphone without turn my screen horizontaly.

Potential solution

Adapt the css for each big kind of resolution with usage of @media

Filter Event by Cycle

Expected behaviour

There should be a way of getting events in a specific cycle.

Current behavior

We can only get ALL events through /events GET

Potential solution

Add a filter in the /events GET view. We should be able to add "?cycle=cycle_id" in the url to get specific events.

Manage users

Expected behaviour

We want to be able to :

  • signup
  • activate our account
  • get information about a given user
  • list users

Current behavior

Actually we have no calls on the API
We do not have models too

Potential solution

  • Create models
  • Create views (calls of the API)
  • Create a serializer for basic user like : BasicUserSerializer

1 - Create new user :

  • URL : POST users/
  • No authentication required
  • params POST : username, email, password
  • return : the new user serialization

User.is_active = False at this step of the creation
Un email de bienvenue est envoye au user afin de valider son inscription (https://www.sendinblue.com)

2 - Detail of a user :

  • URL : GET users/$id
  • Restricted to admin only
  • return : the user serialization

3 - Activate a user :

  • URL : POST users/
  • No authentication required
  • params POST : activation-token
  • return : the new user serialization

4 - List all user :

  • URL : GET users/
  • Restricted to admin only
  • return : the user serialization

Add pagination on the API

Expected behaviour

We want to be able to use a system of pagination when we use the API

Current behavior

Actually all objects are returned in a unique JSON

Potential solution

Use the system of pagination of Django Rest Framework

Install/Update script for developer

Expected behaviour

We want to be able to just launch a script to init all the project in local.

Current behavior

Actually we need to follow the INSTALL.md file.

Potential solution

Add a script in script folder at the root of the repository.

Better addresses handling (model)

Expected behaviour

Admin site could provide advanced features such as auto-complete and manual location on map using long/lat. The API should regularize addresses it receives.

Current behavior

The current address system is very basic. It should be more robust.

  • There are some feature missing like auto-complete using OpenStreetMap of GoogleMap on the admin site.
  • A map widget would also be useful on the admin site.
  • Addresses that are manually added are not verified, so there can be duplicates.

Potential solution

There are a couple of tools/resources available, although not all maintained.

  • libpostal : A C library for parsing/normalizing street addresses around the world. Powered by statistical NLP and open geo data.
  • django-address : A Django address model and field. Addresses may be specified by address components or by performing an automatic Google Maps lookup.
  • GeoDjango Model API : This document explores the details of the GeoDjango Model API.

Forbid user to delete a participation if the event is already begin

Expected behaviour

I don't want the user to be able to delete his participations if the event linked is already begin.

Current behavior

Use can delete all his participations

Potential solution

Check to add this logic in the serializer or/and in the models to be sure it's impossible to do that.

Allow users to change their personnal informations

Expected behaviour

I want to be able to change my personnals informations

Current behavior

Actually i need to contact an administrator to change my informations and my password

Potential solution

  1. Create a new endpoint to edit a user PATCH /users/:id
  2. If the user want to change his password, ask :
    • actual_password
    • new_password
    • confirm_password

PATCH doesn't use `partial_update()`

Expected behaviour

When i call the API with a HTTP PATCH verb i want to make a partial update of the ressource.

Current behavior

Actually we call the update() function of the view and not the partial_update() who make only a partial update.

def patch(self, request, *args, **kwargs):
    if self.request.user.has_perm('volunteer.update_cell'):
        return self.update(request, *args, **kwargs)

Potential solution

Change :

return self.update(request, *args, **kwargs)

to :

return self.partial_update(request, *args, **kwargs)

on each view already implemented (EventsId is already done)

Step to reproduce (if it's a bug)

No need to reproduce, just look the code.

Your environment (if it's a bugs)

  • Version used : Develop (commit : c2cd8d19ad4e0d196ac22b33fcb2b6b9576adba2)
  • Version of softwares (python, firefox, chrome, ..) : No need
  • Operating System (Windows, Mac, Ubuntu, ArchLinux, ..): No need

Manage TaskType

Expected behaviour

We want to be able to use a CRUD on TaskType objects.

Current behavior

Actually we have no calls on the API
We do not have models too

Potential solution

  • Create models
  • Create views (calls of the API)
  • Create a serializer for admin like : AdminTaskTypeSerializer

1 - Create new TaskType :

  • URL : POST tasktypes/
  • Restricted to admin only
  • params POST : name
  • return : the new tasktype serialization

2 - Delete a tasktype :

  • URL : DELETE tasktypes/$id
  • Restricted to admin only
  • params POST : no one
  • return : nothing

3 - Update a tasktype :

  • URL : PATCH tasktypes/$id
  • Restricted to admin only
  • params POST : name
  • return : the tasktype serialization (complete)

4 - List tasktypes :

  • URL : GET tasktypes/
  • Restricted to admin only
  • return : a list of all tasktypes serialization

5 - Detail of a tasktype :

  • URL : GET tasktypes/$id
  • Restricted to admin only
  • return : the tasktype serialization

Add __str__() method to existing models

Expected behaviour

Models should have a str() method to get a meaningful representation on the objects.

>>> TaskType.objects.all()
<QuerySet [<TaskType: tasktype_name>]>

Current behavior

No str() method are defined in the models. That means, for example, that when we query a set of objects of a model in the shell, we get something like

>>> TaskType.objects.all()
<QuerySet [<TaskType: TaskType object>]>

Potential solution

The method whould be added (TaskType and Cycle). See the Django Tutorial for more details.

New system of notification

Expected behaviour

Allow system to give some notification to some users

Current behavior

We don't have a system of notification

Potential solution

  • Create a new model Notification
  • Update model Profile to have some new preferencies (default=False)
  • Create a new signals to launch email when a new Notification is created
  • Add endpoint GET notifications/
  • Add endpoint GET notifications/:id

tp1d2i9038nteknsqxx0xowlboaeqmbjge7vwka4hroxowuanpxlyf9yumifhicktw6oc6fshfdumza90vttdvpooud85tt2vqgu0dgxdim-07fc3dopzr3hi8t1e5yhcmkb8wzdufbx79ljtltmknhxojv67dprnr9lz8uf58xow4xiito_fdhz8mjyn6ora8vd6dxo7hs8wv0remdopan-p0i0

@startuml

title Notification System - Class Diagram


class Notification {
    +TextField content
    +CharField title
}

class User {
}

class Profile {
    + ...
    +BooleanField send_email
    +BooleanField send_sms
    + ...
}

Notification -> User : notify > 
User -> Profile
@enduml

Initiate new SCSS prototype

Expected behaviour

We want to be able to develop a new prototype of user interface with SCSS with a all-in-one project easy to use to new contributor

Current behavior

It's a new part of the project, so we don't have a current behavior

Potential solution

  • Use Gulp to generate CSS file
  • Create a file archirecture to manage the design with SCSS
  • Create build **AND ** watch job with Gulp
    • build : Build the new css file from all scss files
    • watch : Launch build on EACH change to have a realtime refresh when we code

Contributing documentation

Expected behaviour

I want to find a page of documentation on how to contribute to this project.

Current behavior

I've no one information for the moment.

Potential solution

  1. Add a page How to contribute in the documentation ReadTheDocs
  • How to find an issue (waffle, github)
  • How to commit
  • Test Driven Development
  • Inform you work on an issue by commenting this one before you begin to work on it (or assign yourself if you're a member of the organization)
  • How to name your branch (prefix + snake_case, ex: enhancement-create_new_cell, fix-pep8_standard_on_cell_model)
  1. Modify the template of Pull Request to make a link on the contribution page in place of the Contributing.md who doesn't exist

Manage Cycle

Expected behaviour

We want to be able to use a CRUD on Cycle objects.

Current behavior

Actually we have no calls on the API
We do not have models too

Potential solution

  • Create models
  • Create views (calls of the API)
  • Create a serializer for admin like : AdminCycleSerializer

1 - Create new cycle :

  • URL : POST cycles/
  • Restricted to admin only
  • params POST : start, end
  • return : the new cycle serialization

2 - Delete a cycle :

  • URL : DELETE cycles/$id
  • Restricted to admin only
  • params POST : no one
  • return : nothing

3 - Update a cycle :

  • URL : PATCH cycles/$id
  • Restricted to admin only
  • params POST : start, end
  • return : the cycle serialization (complete)

4 - List cycles :

  • URL : GET cycles/
  • Restricted to admin only
  • return : a list of all cycle serialization

5 - Detail of a cycle :

  • URL : GET cycles/$id
  • Restricted to admin only
  • return : the cycle serialization

Standard for docstring

Expected behaviour

We want to have a documentation of contributing about docsting to know how to write them.

Current behavior

We write docstring the way we want without coordination.

Potential solution

Add some information in the contributing file

Endpoint to get personnal information

Expected behaviour

I want to be able to find my personals information with an endpoint on the API.

Current behavior

I can get my token with the authenticate endpoint but i can't find my personnal ID or all my personnal informations.

Potential solution

Create a new endpoint `users/me' to get my personnal informations.
To call this endpoint you need to be authenticated with your token API.

Allow users to know the number of volunteer and on_hold when they list events

Expected behaviour

I want to know the number of volunteers and standby already attached on an event when i list all event with GET /events

Current behavior

Actually i have nb_volunteers_needed, nb_volunteers_on_hold_needed and volunteers but i can't know who is volunteer and who is on_hold.

Potential solution

Add two method property on the model and add them on the serializer

Endpoint to manage participations

Expected behaviour

We want to be able to manage participations with some endpoints

Current behavior

Actually we can manage participation from the event endpoint but it's not safe and not easy to use.

Potential solution

Create some new endpoint :

  • /participations (GET and POST)
  • /participations/$id (GET, PATCH and DELETE)

Forbid the modifications on event serializers (put the fields as read-only)

Add some factories to manage models in tests

Expected behaviour

I want to be able to create a fake instance of a model easily without manually create all the requirements of this models (relatel field and specific values)

Current behavior

I need to create ALL the requirements to just test a property of a model.

Potential solution

Create some factories in factories.py file in each applications of the project.

Add pycodestyle to requirement

Expected behaviour

I expect to have all needed packages for dev by installing requirement file's content

Current behavior

pip requirement file does not contain pep8 (deprecated) nor pycodestyle

Potential solution

Add pycodestyle to pip requirements.
Otherwise we'll need an easy solution for developers.

Also, Travis is using pep8. Shouldn't it be using pycodestyle?
ref:
PyCQA/pycodestyle#572
PyCQA/pycodestyle#466

Send email to user when a new participation is created

Expected behaviour

As a user, i want to receive an email of confirmation when i ask to participate to an event.

Current behavior

Actually i just have a notification on the website and i can see my schedule on the website.
I can't see my schedule without go on the website.

Potential solution

  1. Add a new template of email in the settings
  2. Call the template with imailing with this list of attributs :
    • start_date : An human readable date (because it's just copy/paste in the template)
    • start_time : An human readable time (because it's just copy/paste in the template)
    • address
  3. Add a boolean in the settings file to send this kind of email or not at each new participations

mock-api update reminder

Expected behaviour

The PR template should remind the contributor to update the mock-api file when adding API endpoints.

Current behavior

No mention of the mock API is made.

Potential solution

Update de template.

Add important checks in PR template

Expected behaviour

PR template should list some of the most important checks from the CONTRIB doc

Current behavior

The PR template only includes some of the important check (like branch name)

Potential solution

Add important elements in .github/PULL_REQUEST_TEMPLATE.md

First unit test + CI

Expected behaviour

We want to add Unit test and Coverage in our structure of Continuous Integration.

On each commit we want the system to test if :

  • unit test are all successful
  • coverage did not decrease

Current behavior

Actually we already have a structure of Continuous Integration based on Travis
This structure only test the PEP8 standard.

Potential solution

  • Create UserFactory to create a new user :
    • Option to be superuser
    • Option to have a specific password
    • Option to have a specific username
  • Create a first test on authentication POST call
  • Add unit test execution on Travis (travis.yml)
  • Configure Coveralls on the project
    • Integration of Coveralls with the Github project
    • Add coverage in travis.yml
    • Add the coverage badge in the readme

Upgrade of participation's admin panel

Expected behaviour

Add a search bar to find participation of a specific user
Add filters on the table
Splits line of the table into multiple columns

Current behavior

Actually we have just a list of one columns str() and no way to search and filter

Potential solution

Overwrite the AdminModel in the admin.py

Integration of transactional email

Expected behaviour

We want to activate the user by default
OR
We want to send him an email with the activation token to activate his account

Current behavior

User is put inactive when created and that's all because he never get his ActivationToken

Potential solution

Use the package created by myself and @willkoua to send email by transactional service (Sendgrid, SendinBlue, ..) or put the user active by default.

Wrong response from POST /authentication

Expected behaviour

When the user is not activated, if we try to get a token (login), the /authentication POST endpoint should return an error message informing the user of the situation.

Current behavior

This response is sent when a user is not activated and tries to login:

{
  non_field_errors: [
    "Bad password"
  ]
}

Potential solution

Verify if the user is activated before sending back the "bad password" error.

Step to reproduce (if it's a bug)

  1. Create a User using the /user POST endpoint
  2. Try to get a token using the /authentication POST endpoint.
  3. You should get a "Bad password" error.

Your environment (if it's a bugs)

  • Version used (latest commit):
commit d355c5a6d6ff537b5eeaaae25a2357e3f59a9dba (HEAD -> develop, upstream/develop, origin/develop, origin/HEAD)
Author: RignonNoel <[email protected]>
Date:   Sat Dec 30 14:18:49 2017 -0500

    add filter on event to manage M2M relation
  • Version of softwares (python, firefox, chrome, ..) : Python 3.6.2, Chrome Version 60.0.3112.90 (Build officiel) (64 bits)
  • Operating System (Windows, Mac, Ubuntu, ArchLinux, ..): ArchLinux

Manage Event

Expected behaviour

We want to be able to use a CRUD on Events objects.

Current behavior

  • No calls related to Events in the API
  • No Events model

Potential solution

  • Create the Events model
  • Create views (endpoints of the API)
  • Create user/admin serializers like : AdminEventSerializer

Model representation:

Event:
    - name (charfield)
    - nb_volunteers_needed (number)
    - nb_volunteers_standby_needed (number)
    - cycle (Cycle ForeignKey)
    - task_type (Tasktype ForeignKey)
    - volunteers (User ManyToManyField)
    - volunteers_standby (User ManyToManyField)

Some methods that could be useful:

def nb_volunteers(self)
def nb_volunteers_standby(self)

1 - Create new event :

  • URL : POST events/
  • Restricted to admin only
  • params POST : name,task_type,nb_volunteers_needed,nb_volunteers_standby_needed,volunteers,volunteers_standby
  • returns : the new event serialization

2 - Delete an event :

  • URL : DELETE events/$id
  • Restricted to admin only
  • params DELETE : none
  • returns : nothing

3 - Update a event :

  • URL : PATCH events/$id
  • Restricted to admin only
  • params PATCH : name,task_type,nb_volunteers_needed,nb_volunteers_standby_needed,volunteers,volunteers_standby
  • returns : the event serialization (complete)

4 - List events :

  • URL : GET events/
  • Restricted to admin only
  • returns : a list of all events serialization

5 - Detail of an event :

  • URL : GET events/$id
  • Restricted to admin only
  • returns : the event serialization

translations of error message

Expected behavior

I want to receive all messages from the API in my preferred language.

Current behavior

Actually all error message from the API is in English,

Potential solution

  • Make translation of all error/success message of the API
  • Allow change the language in the settings

Allow user to filter Participation by start_date

Expected behaviour

I want to be able to get only my future participation to prepare my schedule.

Current behavior

I can only get ALL my participations and filter after that

Potential solution

Add four filters :

  • start_date_lte
  • start_date_gte
  • end_date_lte
  • end_date_gte

Manage Cell

Expected behaviour

We want to be able to use a CRUD on Cells objects.

Current behavior

Actually we have no calls on the API
We do not have models too

Potential solution

  • Create models
  • Create views (calls of the API)
  • Create a serializer for admin like : AdminCellSerializer

1 - Create new cell :

  • URL : POST cells/
  • Restricted to admin only
  • params POST : name
  • return : the new cell serialization

2 - Delete a cell :

  • URL : DELETE cells/$id
  • Restricted to admin only
  • params POST : no one
  • return : nothing

3 - Update a cell :

  • URL : PATCH cells/$id
  • Restricted to admin only
  • params POST : name
  • return : the cell serialization (complete)

4 - List cells :

  • URL : GET cells/
  • Restricted to admin only
  • return : a list of all cell serialization

5 - Detail of a cell :

  • URL : GET cells/$id
  • Restricted to admin only
  • return : the cell serialization

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.