Git Product home page Git Product logo

django-survey's Introduction

Build Status Coverage Status PyPI version Code style: black PRs Welcome

Django survey

A django survey app that can export results as CSV or PDF using your native language.

django-survey-and-report on pypi. Based on and compatible with django-survey. You will be able to migrate your data from an ancient version of django-survey, but it has been ported to python 3, and you can export results as CSV or PDF using your native language.

Professional support for django-survey-and-report is available as part of the Tidelift Subscription

Table of contents

Language available

The software is developed in english. Other available languages are :

Getting started

Add django-survey-and-report to your requirements and get it with pip.

echo 'django-survey-and-report' >> requirements.txt
pip install -r requirements.txt

Add bootstrapform and survey in the INSTALLED_APPS in your settings :

INSTALLED_APPS = [
	# Your own installed apps here
]

from pathlib import Path

CSV_DIRECTORY = Path("csv") # Define the directory where csv are exported
TEX_DIRECTORY = Path("tex") # Define the directory where tex files and pdf are exported

INSTALLED_APPS += [
	'bootstrapform',
	'survey'
]

Add a URL entry to your project’s urls.py, for example:

from django.conf import settings
from django.conf.urls import include

try:
    from django.conf.urls import url
except ImportError:
    # Django 4.0 replaced url by something else
    # See https://stackoverflow.com/a/70319607/2519059
    from django.urls import re_path as url

urlpatterns = [
    # Your own url pattern here
]

if 'survey' in settings.INSTALLED_APPS:
    urlpatterns += [
        url(r'^survey/', include('survey.urls'))
    ]

Note: you can use whatever you wish as the URL prefix.

You can also change some options:

# Permit to open the csv in Excel without problem with separator
# Using this trick : https://superuser.com/a/686415/567417
EXCEL_COMPATIBLE_CSV = True

# The separator for questions (Default to ",")
CHOICES_SEPARATOR = "|"

# What is shown in export when the user do not answer (Default to "Left blank")
USER_DID_NOT_ANSWER = "NAA"

# Path to the Tex configuration file (default to an internal file that should be sufficient)
from pathlib import Path
TEX_CONFIGURATION_FILE = Path("tex", "tex.conf")

# Default color for exported pdf pie (default to "red!50")
SURVEY_DEFAULT_PIE_COLOR = "blue!50"

To uninstall django-survey-and-report, simply comment out or remove the 'survey' line in your INSTALLED_APPS.

If you want to use the pdf rendering you need to install xelatex. If you're using the Sankey's diagram generation you will also have to install python-tk (for python 2.7) or python3-tk (for python 3.x).

Making a survey

Using the admin interface you can create surveys, add questions, give questions categories, and mark them as required or not. You can define choices for answers using comma separated words.

Creating of a question

The front-end survey view then automatically populates based on the questions that have been defined and published in the admin interface. We use bootstrap3 to render them.

Answering a survey

Submitted responses can be viewed via the admin backend, in an exported csv or in a pdf generated with latex.

Generating a pdf report from the survey's result

There is a default configuration for PDF generation, but you might want to change TEX_CONFIGURATION_FILE for better results (in particular for language other than english).

You can manage the way the report is created in a yaml file, globally, survey by survey, or question by question. In order to render pdf you will need to install xelatex. You will also need python3-tk for sankey's diagram.

The results are generated for the server only when needed, but you can force it as a developer with:

python manage.py exportresult -h

Following is an example of a configuration file. you can generate one with:

python manage.py generatetexconf -h

Basic example

generic:
  document_option: 11pt
"Test survëy":
  document_class: report
  questions:
    "Lorem ipsum dolor sit amët, <strong> consectetur </strong> adipiscing elit.":
      chart:
        type: polar
        text: pin
    "Dolor sit amët, consectetur<strong>  adipiscing</strong>  elit.":
      chart:
        type: cloud
        text: inside

The pdf is then generated using the very good pgf-pie library.

The generated pdf for the polar and pin options

The generated pdf for the cloud and inside options

Sankey diagram

If you installed python3-tk, you can also show the relation between two questions using a sankey diagram :

"Lorem ipsum dolor sit amët, <strong> consectetur </strong> adipiscing elit.":
  chart:
    type: sankey
    question: "Dolor sit amët, consectetur<strong>  adipiscing</strong>  elit."

You get this as a result:

The generated pdf for the sankey example

Advanced example

You can also limit the answers shown by cardinality, filter them, group them together and choose the color for each answer or group of answers.

If you use this configuration for the previous question:

"Test survëy":
  "Dolor sit amët, consectetur<strong>  adipiscing</strong>  elit.":
    multiple_charts:
      "Sub Sub Section with radius=3":
        color:
          Yës: blue!50
          No: red!50
          Whatever: red!50!blue!50
        radius: 3
      "Sub Sub Section with text=pin":
        group_together:
          Nah:
            - No
            - Whatever
          K.:
            - Yës
        color:
          Nah: blue!33!red!66
          K.: blue!50
        text: pin
    chart:
      radius: 1
      type: cloud
      text: inside

You get this as a result:

The generated pdf for the multiple charts example

Implementing a custom treatment

If you want to make your own treatment you can use your own class, for example.

Configuration:

"Test survëy":
  questions:
    "Ipsum dolor sit amët, <strong> consectetur </strong>  adipiscing elit.":
      chart:
        type: survey.tests.exporter.tex.CustomQuestion2TexChild

Code in survey.tests.exporter.tex.CustomQuestion2TexChild:

from survey.exporter.tex.question2tex_chart import Question2TexChart


class CustomQuestion2TexChild(Question2TexChart):

    def get_results(self):
        self.type = "polar"
        return """        2/There were no answer at all,
        3/But we have a custom treatment to show some,
        2/You can make minor changes too !"""

Result:

The generated pdf for the custom example

For a full example of a configuration file look at example_conf.yaml in doc, you can also generate your configuration file with python manage.py generatetexconf -h, it will create the default skeleton for every survey and question.

To guide you during the python development, you can read:

Do not hesitate to make a pull request with your new exporter if it can be of interest for others I'll integrate it.

Credits

Based on jessykate's django-survey, and contribution by jibaku, joshualoving, and ijasperyang in forks of jessykate's project.

We use anazalea's pySankey for sankey's diagram during reporting.

django-survey's People

Contributors

anthonyrandell avatar antonofthewoods avatar capaci avatar d-horner avatar ddhira123 avatar digglife avatar fibio avatar g-normand avatar giliam avatar gjelsas avatar guam68 avatar jessykate avatar m-rm avatar manchos avatar maximloginov avatar nsuzue avatar ongraphpythondev avatar ordonja avatar paleneutron avatar pierre-sassoulas avatar pre-commit-ci[bot] avatar psass-antidot avatar quimey avatar rhenanbartels avatar roottool avatar saschalalala avatar sotiriszogos avatar telomeraz avatar tmilliman avatar zehengl avatar

Stargazers

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

Watchers

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

django-survey's Issues

Add language for internationalisation

The software is developed in english. Other available languages are :

Language asked by a user, but not available yet:

  • Hindi
  • Hungarian

If you're susceptible of using django-survey in a language that is not available, making and giving back the translation with a pull request would be very helpful.

Add your language in the LANGUAGE variable in the settings, like here.

Then you can translate with :

python manage.py makemessages
# python manage.py createsuperuser ? (You need to login for rosetta)
python manage.py runserver
# Access http://localhost:8000/admin to login
# Then go to http://localhost:8000/rosetta to translate
python manage.py makemessages --no-obsolete --no-wrap

If your language is not yet available in rosetta, this stack overflow question should work even for a language not handled by Django : https://stackoverflow.com/questions/12946830/

Do not forget to credit yourself like in the header see here

Only single page survey are working reliably

Because my survey used a single page for everything the other options are not guaranteed to work.

Some possible option to check and/or add in Survey would be :

  • Creating formular by category whatever the number of question inside them is
  • Creating formular with a Paginator (always the same number of question by page) whatever the categories of the question are
  • Creating formular with a single question for every page

Everything that should be changed for formular generation is in survey/forms.py.

Customize url for survey and redirect url after finishing survey?

Hi,

I'm a new user of django-survey. I want to embed a survey on my website and when users finish the survey I want to redirect them to some other page. I wonder is it possible to customize the url for a survey and the redirect url after finishing one survey?

Thanks!

Wrong settings with Pip 10.0

In pip 10.x colorama isn't located at from pip.utils.logging import colorama this should be changed to from pip._vendor import colorama

Aggregating results

I appreciate this might be out of scope, but I thought I would ask here first.

I am trying to build an admin summary of the results, grouping ChoiceFields by their answer. I've been having some trouble getting the csv, tex and pdf reports working, so I am unable to sort out how this data is aggregated or whether it is.

Has anyone developed a way to display a count of the answers for each question?

Enhancement: Static Folder structure

Hi,
I believe it would be a better practice to have the static folder reorganized adding a "survey" folder before the js, jss, and fonts folder.

  • static
    -- survey
    ---- js
    ---- css
    ---- fonts

In this way, we can do a python3 manage.py collectstatic and every app we have installed in our projectwill have its own static files without mixing them between.

More than an issue it's a question

After ends a survey I want to have completed.html messages instead confirm.html, like

Sorry! Your already replied to our survey

Where can I set that?
Sorry me, I'm newbie with django

The use of this library for survey's with dynamic sections?

We have a need for an app that contains a survey, but the requirements of the survey are such that the sections of the survey are repeated multiple times. For example:

Q: How many people are involved? (Answer: 2)

For person 1:

  • Q: What is there name?
  • Q: What is there age?

For person 2:

  • Q: What is there name?
  • Q: What is there age?

There would also need to be a way to access the data for reporting - or at least for passing it to a template for presentation.

Assuming the existing library does not contain this functionality, what do you think the complexity of adding such a capability would be? Unreasonable? Easy? Somewhere in between?

Thanks!

Logged users can't answer a survey more than one time

So, this basically is not a bug but i would like my users to answer the questionnaire more than once!!
How can that be done? As when a user logs in and answer the survey it is stored with a unique key, but when the same user come back to take the same survey the previous data come on the form and when he submits it it is updated in the database!! I want the user to reply to the survey again and it should save it with a different unique key!!

Can you please help me achieve my condition?

And secondly there are some issues with the exporting commands it seems like the commands are working in the cmd but it does not actually provide a generated file for either csv, pdf or any other form!

'Settings' object has no attribute 'CHOICES_SEPARATOR'

Hello guys!

I'd like to say first of all that I'm quite new to Django.

I created a Django Project with pyCharm and installed this package using "pipenv install --pre django-survey-and-report". Everything seems to go fine. I add the app to INSTALLED_APPS just like you say in your documentation but then, when I create a survey, I get the error:

Request Method: POST
http://127.0.0.1:8000/admin/survey/survey/add/
2.1.9
AttributeError
'Settings' object has no attribute 'CHOICES_SEPARATOR'
C:\Users\jgarcia.virtualenvs\Surveys-8COo6NzA\lib\site-packages\django\conf_init_.py in getattr, line 58
C:\Users\jgarcia.virtualenvs\Surveys-8COo6NzA\Scripts\python.exe

Any idea of why this may be happening?

Thank you in advance!

Create Survey from shell?

Is there a possibility to create a Survey from the commandline? I could not find an easy way to script the creation of a survey.
Thanks for your Work!

More documentation for customization of reports

Is there somewhere more information about the report function? I would like percentages and the sum of total votes, for example. If you could provide more detailed information about the possibilities of the report function, it would be very welcome!!

Maybe there is some external documentaion of the used code?

Thanks for your work!

Image upload Error

This is one error

PIL.Image.init() l.430 - Image: failed to import MicImagePlugin: No module named 'olefile'

Above came in the cmd

AttributeError at /survey/3/ 'ImageSelectWidget' object has no attribute 'template_name'

this one was shown on the browser

And can we have multiple image choices in the survey question? And can I have a part where i can show a video in the survey either by a link or by having it on my server machine!

Missing djangocms-rosetta in libs.

I had this issue when trying to migrate the application.

ModuleNotFoundError: No module named 'rosetta.urls'

installed djangocms-rosetta : pip install djangocms-rosetta fixed the issue.
Maybe it will be great to add it to your dependencies ?

A+

@models.permalink no longer supported

In survey/models @models.permalink has been deprecated since Django 1.11. It was recommended to be changed to a reverse call inside of the function instead. In Django 2.1, the decorator simply fails.

Reusable App

Is there anyway to use this as part of an existing django project?

Transition to Django 2.0 and supporting only python 3+

The Django 1.11.x series is the last to support Python 2.7. We tried to support both python 2.7 and python 3+ until then. We now need to be able to run django 2.0 and we can't keep the compatibility. In order to have a compatible version for both python version we need two branchs.

For example, here, everything has only one purpose : compatibility with python 2.7. :

# -*- coding: utf-8 -*-

from __future__ import (
    absolute_import, division, print_function, unicode_literals
)

from builtins import object, open
from future import standard_library

standard_library.install_aliases()

There will also be some change related to the transition from django 1.11 to django 2+ too.

What need to be done :

  • Release the last version compatible with python 2.7 and django 1.11 (django-survey-and-report-py27 ?)
  • Create a (dead) branch for python 2.7 and django 1.11 in case someone want to support it
  • Clean the generic code for python 3 (python 2to3 should help)
  • Clean the code in order to support Django 2.0 and 2.1 (See #15, #16, #17)
  • Release a new version compatible with python 3 only

Not a pluggable app in django 2.1

This app was initially used with an old django version by copying the directory to the other project. Being a fully plugable app using the last django version would be very useful in order to be more easily usable.

Incorrect rendering of radio values with unicode symbols

Hello there!
I recognized that if I try to use unicode choices like ["Женщина", "Мужчина"] then in template I get <input value="">, hence it's not possible to send form because every time you'll get "the value '' is not within possible values".

The reason is in Question model.

    def get_choices(self):
        """
        Parse the choices field and return a tuple formatted appropriately
        for the 'choices' argument of a form widget.
        """
        choices_list = []
        for choice in self.get_clean_choices():
            choices_list.append((slugify(choice), choice))
        choices_tuple = tuple(choices_list)
        return choices_tuple

slugify is standard django function which has this implementation:

@keep_lazy(str, SafeText)
def slugify(value, allow_unicode=False):
    """
    Convert to ASCII if 'allow_unicode' is False. Convert spaces to hyphens.
    Remove characters that aren't alphanumerics, underscores, or hyphens.
    Convert to lowercase. Also strip leading and trailing whitespace.
    """
    value = str(value)
    if allow_unicode:
        value = unicodedata.normalize('NFKC', value)
    else:
        value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore').decode('ascii')
    value = re.sub(r'[^\w\s-]', '', value).strip().lower()
    return mark_safe(re.sub(r'[-\s]+', '-', value))

As you can see, by default slugify will remove all unice symbols.

So I managed to create my own get_choices function and use it in my form class. Like this

# coding=utf-8
from django.utils.text import slugify
from survey import forms as survey_forms
from django import forms
from survey.models import Question
from survey.widgets import ImageSelectWidget


class CustomRadioInput(forms.RadioSelect):
    option_template_name = 'radio_option.html'
    template_name = 'radio.html'


def my_get_choices(question):
    """
    Parse the choices field and return a tuple formatted appropriately
    for the 'choices' argument of a form widget.
    """
    assert isinstance(question, Question), 'question must be survey.Question object'
    choices_list = []
    for choice in question.get_clean_choices():
        choices_list.append((slugify(choice, allow_unicode=True), choice))
    choices_tuple = tuple(choices_list)
    return choices_tuple


class MyResponseForm(survey_forms.ResponseForm):

    WIDGETS = {
        Question.TEXT: forms.Textarea,
        Question.SHORT_TEXT: forms.TextInput,
        Question.RADIO: CustomRadioInput,
        Question.SELECT: forms.Select,
        Question.SELECT_IMAGE: ImageSelectWidget,
        Question.SELECT_MULTIPLE: forms.CheckboxSelectMultiple,
    }

    def get_question_choices(self, question):
        """ Return the choices we should use for a question.

        :param Question question: The question
        :rtype: List of String or None """
        qchoices = None
        if question.type not in [Question.TEXT, Question.SHORT_TEXT,
                                 Question.INTEGER]:
            qchoices = my_get_choices(question)
            # add an empty option at the top so that the user has to explicitly
            # select one of the options
            if question.type in [Question.SELECT, Question.SELECT_IMAGE]:
                qchoices = tuple([('', '-------------')]) + qchoices
        return qchoices

So it seems like we need to change slugify function usage in Question model or even more: create settings parameter to pass allow_unicode option.

The user is able to take the survey even when Survey.is_published is False

Hi,
I am fairly new to Django and I could not understand a few things

In the file survey.py what is the use of the fields:
is_published The user is able to take the survey and submit response even if the survey has not been published
display_by_question Keeps iterating over the required questions. Response doesn't get submitted and
template Throws an exception "TemplateDoesNotExist" if any value is entered in the template field?

"You can always come back and change them." Is displayed wrongly

Even if the survey is one write only the success message reads

You can always come back and change them.

Hitting the back button or reloading the page doesn't allow reanswering the questions, but the message is always displayed. There should be logic to show this message only if the checkbox "users can alter their answers afterwards" is checked.

Select tag not displayed properly

Fix could be in survey/templates/survey/question.html displaying form directly instead of itering on field.

It's also possible to use bootstrap-form directly to render form.

Clone survey

I have a need to issue the same survey each week and it would be great to be able to clone the survey complete with all questions to a new survey and provide a new title.

Add an option to prevent user from modifying their response

  1. Can we restrict the number of responses that we get from a user?
    According to my understanding, right now a user can edit and submit the form n number of times and the last response gets recorded.
    Instead is there a way to disable the survey in list.html page for a survey as soon as it is submitted?

  2. Is there a provision to deactivate the survey after n number of days?

Trouble with export to csv

I am trying to export to CSV and am getting an error about NoneType:

$ ../manage.py exportresult --survey-id 4 --csv
Traceback (most recent call last):
  File "../manage.py", line 21, in <module>
    main()
  File "../manage.py", line 17, in main
    execute_from_command_line(sys.argv)
  File "/home/otcomm/otcomm/otcommenv/lib/python3.6/site-packages/django/core/management/__init__.py", line 381, in execute_from_command_line
    utility.execute()
  File "/home/otcomm/otcomm/otcommenv/lib/python3.6/site-packages/django/core/management/__init__.py", line 375, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/home/otcomm/otcomm/otcommenv/lib/python3.6/site-packages/django/core/management/base.py", line 323, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/home/otcomm/otcomm/otcommenv/lib/python3.6/site-packages/django/core/management/base.py", line 364, in execute
    output = self.handle(*args, **options)
  File "/home/otcomm/otcomm/otcommenv/lib/python3.6/site-packages/survey/management/commands/exportresult.py", line 78, in handle
    exporter.generate_file()
  File "/home/otcomm/otcomm/otcommenv/lib/python3.6/site-packages/survey/exporter/survey2x.py", line 91, in generate_file
    f.write(self.survey_to_x())
  File "/home/otcomm/otcomm/otcommenv/lib/python3.6/site-packages/survey/exporter/csv/survey2csv.py", line 70, in survey_to_x
    line = Survey2Csv.get_user_line(question_order, response)
  File "/home/otcomm/otcomm/otcommenv/lib/python3.6/site-packages/survey/exporter/csv/survey2csv.py", line 36, in get_user_line
    answers = answer.values
  File "/home/otcomm/otcomm/otcommenv/lib/python3.6/site-packages/survey/models/answer.py", line 51, in values
    if len(self.body) < 3 or self.body[0:3] != "[u'":
TypeError: object of type 'NoneType' has no len()

Select widget problem

Hi,

I'm a new user of django-survey. I encountered a problem in displaying a question type select . As i understood, the form.select widget would make the html code but in my case the html code of a question type select in the form doesn't contain tag, so it dipslay the choices as options without a dropdown list. I can't seem to resolve the problem. Thanks for the help !

Permit to modify questions displayed by taking previous answers into account

The survey that my project creates are simple questions, but I want to add constraints in a sense that when a question A (Are you married?) is asked with options 'married', 'unmarried'. If the answer for question A is 'married' then I should get question B(How many kids do you have?) or if the answer is 'unmarried' then I should not get question B and get question C('any other question'). Now the problem is I cannot have if-elif-else conditioning written there for this purpose as the data (questions and options) are coming dynamically, like on runtime!

Trying to create result in pdf format failed

I try to generate a pdf result from a poll, but it stopps with:
sh: 1: xelatex: not found sh: 1: xelatex: not found

I think there is some path related issue here, but I keep looking at your code and don't see what I'm doing wrong.

It creates the .tex file, but aborts afterwards. I think the conversion tex to pdf is not working.

Some more of the output is:
survey.exporter.tex.latex_file.__init__() l.24 - Creating a document skeleton with document_class=article, document_option=12pt survey.exporter.tex.survey2tex.treat_question() l.40 - Treating, 1 Wiedereinladung erwuenscht? survey.exporter.tex.configuration.check_survey_exists() l.50 - Checking that 'TestDirigentin' is an existing survey. survey.exporter.tex.survey2tex.treat_question() l.40 - Treating, 2 Kandidat für Chefdirigent survey.exporter.tex.configuration.check_survey_exists() l.50 - Checking that 'TestDirigentin' is an existing survey. survey.exporter.survey2x.generate_file() l.92 - Wrote tex in /app/survey/tex/testdirigentin.tex sh: 1: xelatex: not found sh: 1: xelatex: not found

Thank you for your work!

Possibility for vertical checkbox/radio button display

It would be nice to have a convenient way of choosing if you want to display question choices horizontally or vertically. Possible implementations:

  • For a simple yes/no/maybe question you may want to render the buttons horizontally
  • For a longer list of choices, horizontal display becomes very messy and a vertical display is preferred

I've tried to get this working with the package, but no sucess yet. Providing a custom renderer (ex. https://stackoverflow.com/questions/5935546/align-radio-buttons-horizontally-in-django-forms) does not work since widgets are loaded by the function get_question_widget, which does not take extra arguments for your widget. This also still has the problem that it must be set for all questions of the same type at once.

I was hoping that someone here has a fix/way of enhancing the package with this feature!

export finishes without error and without exported file

First a big thank you for your work!
When I try to export a report, I get no error message, but I also do not get a file. How do I specify a filename or an export-location?
The command I'm using is:python manage.py exportresult -c conf.yaml --survey-id 1 --tex

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.