master 7bbd234eefef cached
58 files
189.0 KB
44.1k tokens
56 symbols
1 requests
Download .txt
Showing preview only (204K chars total). Download the full file or copy to clipboard to get everything.
Repository: kimlimjustin/google-form-clone
Branch: master
Commit: 7bbd234eefef
Files: 58
Total size: 189.0 KB

Directory structure:
gitextract_9q7rdef_/

├── .deepsource.toml
├── .github/
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   └── feature_request.md
│   └── dependabot.yml
├── .gitignore
├── CODE_OF_CONDUCT.md
├── Dockerfile
├── LICENSE
├── README.md
├── docker-compose.yml
├── form/
│   ├── __init__.py
│   ├── asgi.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── index/
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── migrations/
│   │   ├── 0001_initial.py
│   │   ├── 0002_auto_20201128_2040.py
│   │   ├── 0003_remove_form_see_response.py
│   │   └── __init__.py
│   ├── models.py
│   ├── static/
│   │   └── index/
│   │       ├── HurlUI.css
│   │       ├── form.js
│   │       ├── index.js
│   │       ├── response.js
│   │       ├── responses.js
│   │       ├── score.js
│   │       ├── style.css
│   │       └── viewform.js
│   ├── templates/
│   │   ├── error/
│   │   │   ├── 403.html
│   │   │   └── 404.html
│   │   └── index/
│   │       ├── edit_response.html
│   │       ├── form.html
│   │       ├── form_response.html
│   │       ├── index.html
│   │       ├── layout.html
│   │       ├── login.html
│   │       ├── register.html
│   │       ├── response.html
│   │       ├── responses.html
│   │       ├── score.html
│   │       └── view_form.html
│   ├── templatetags/
│   │   ├── count.py
│   │   ├── generate_color.py
│   │   ├── get_property.py
│   │   ├── get_response.py
│   │   ├── is_response.py
│   │   ├── score.py
│   │   └── to_int.py
│   ├── tests.py
│   ├── urls.py
│   └── views.py
├── manage.py
├── renovate.json
└── requirements.txt

================================================
FILE CONTENTS
================================================

================================================
FILE: .deepsource.toml
================================================
version = 1

[[analyzers]]
name = "python"
enabled = true

  [analyzers.meta]
  runtime_version = "3.x.x"

[[analyzers]]
name = "javascript"
enabled = true

  [analyzers.meta]
  environment = ["browser"]


================================================
FILE: .github/FUNDING.yml
================================================
ko_fi: kimlimjustin

================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''

---

**Describe the bug**
A clear and concise description of what the bug is.

**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error

**Expected behavior**
A clear and concise description of what you expected to happen.

**Screenshots**
If applicable, add screenshots to help explain your problem.

**Desktop (please complete the following information):**
 - OS: [e.g. iOS]
 - Browser [e.g. chrome, safari]
 - Version [e.g. 22]

**Smartphone (please complete the following information):**
 - Device: [e.g. iPhone6]
 - OS: [e.g. iOS8.1]
 - Browser [e.g. stock browser, safari]
 - Version [e.g. 22]

**Additional context**
Add any other context about the problem here.


================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''

---

**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

**Describe the solution you'd like**
A clear and concise description of what you want to happen.

**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.

**Additional context**
Add any other context or screenshots about the feature request here.


================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
- package-ecosystem: pip
  directory: "/"
  schedule:
    interval: daily
    time: "22:00"
  open-pull-requests-limit: 10


================================================
FILE: .gitignore
================================================
*.sqlite3
*.sqlite3-journal
*.pyo
*.pyc
data

================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct

## Our Pledge

In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.

## Our Standards

Examples of behavior that contributes to creating a positive environment
include:

* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members

Examples of unacceptable behavior by participants include:

* The use of sexualized language or imagery and unwelcome sexual attention or
 advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
 address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
 professional setting

## Our Responsibilities

Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.

Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.

## Scope

This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at kimlimjustin@gmail.com. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.

Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html

[homepage]: https://www.contributor-covenant.org

For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq


================================================
FILE: Dockerfile
================================================
# syntax=docker/dockerfile:1
FROM python:3
ENV PYTHONUNBUFFERED=1
WORKDIR /code
COPY requirements.txt /code/
RUN pip install -r requirements.txt
COPY . /code/

================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2020 Justin Maximillian Kimlim

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
# Google Forms CLONE

### Demo application and feedback [here](https://google-forms-clone.herokuapp.com/form/in60XZ4GWUswvkaKEOxONvIKkhy4gl/viewform)

![Google Forms clone demo](https://drive.google.com/uc?export=view&id=1GEApyE6aRP74zf2ltmTqpr97NDMHOHbP) 

<details>
<summary>
More screenshots
</summary>

![Google Forms clone demo](https://drive.google.com/uc?export=view&id=1QhPVWHXKApcv5V6FzrHRzut7a5-1Mgp4)
![Google Forms clone demo](https://drive.google.com/uc?export=view&id=1Nwz642ORdTCd6KdsaN28Tt142K3wH-pt)
##### For the best experience, please use a device with a width of at least 350px
- Note that this Google Forms CLONE don't support image uploading due to [Heroku policy](https://help.heroku.com/K1PPS2WM/why-are-my-file-uploads-missing-deleted)

</details>
## Built using:
- Python with Django framework and Jinja templating language
- Vanilla Javascript

## Getting started:
- Clone this repository or fork it
    - To clone this repository type git clone `https://github.com/kimlimjustin/google-form-clone.git` on your command line
    - To fork this repository, click fork button of this repository then type git clone `https://github.com/<your username>/google-form-clone.git`
- Install all the dependencies of this project by typing `pip install -r requirements.txt`
- Migrate the database by typing `python manage.py migrate` on the command line
- Run the project locally by typing `python manage.py runserver` on the command line
    - NB: to run it on your local network, type `python manage.py runserver 0.0.0.0:8000`
- You project will be accessible in your localhost or local network.

## Deployment
For deployment, open `form/settings.py` file and uncomment code from line 131 to 159.

## License
Distributed under the [MIT](https://github.com/kimlimjustin/google-form-clone/blob/master/LICENSE) License. See [`LICENSE`](https://github.com/kimlimjustin/google-form-clone/blob/master/LICENSE) for more information.

## Contact
- Justin Maximillian Kimlim - [kimlimjustin@gmail.com](mailto:kimlimjustin@gmail.com)
- Project link: https://github.com/kimlimjustin/google-form-clone

## Love my work?

<a href='https://ko-fi.com/kimlimjustin' target='_blank'><img height='35' style='border:0px;height:34px;' src='https://az743702.vo.msecnd.net/cdn/kofi3.png?v=0' border='0' alt='Buy Me a Coffee at ko-fi.com' />

================================================
FILE: docker-compose.yml
================================================
version: "3.9"
   
services:
  db:
    image: postgres
    volumes:
      - ./data/db:/var/lib/postgresql/data
    environment:
      - POSTGRES_DB=postgres
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
  web:
    build: .
    command: python manage.py runserver 0.0.0.0:8000
    volumes:
      - .:/code
    ports:
      - "8000:8000"
    depends_on:
      - db
  migration:
    build: .
    command: python manage.py migrate --noinput
    volumes:
      - .:/code
    depends_on:
      - db

================================================
FILE: form/__init__.py
================================================


================================================
FILE: form/asgi.py
================================================
"""
ASGI config for form project.

It exposes the ASGI callable as a module-level variable named ``application``.

For more information on this file, see
https://docs.djangoproject.com/en/3.1/howto/deployment/asgi/
"""

import os

from django.core.asgi import get_asgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'form.settings')

application = get_asgi_application()


================================================
FILE: form/settings.py
================================================
"""
Django settings for form project.

Generated by 'django-admin startproject' using Django 3.1.3.

For more information on this file, see
https://docs.djangoproject.com/en/3.1/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/3.1/ref/settings/
"""

from pathlib import Path

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '5&41du-&cv-cazt$r@k84h*gz-s!*jk2b)131ek^2-lpou#2y4'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80))

ALLOWED_HOSTS = [s.getsockname()[0], '127.0.0.1', 'localhost']
s.close()


# Application definition

INSTALLED_APPS = [
    'index',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'form.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'form.wsgi.application'


# Database
# https://docs.djangoproject.com/en/3.1/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}


# Password validation
# https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


AUTH_USER_MODEL = "index.User"

# Internationalization
# https://docs.djangoproject.com/en/3.1/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.1/howto/static-files/

STATIC_URL = '/static/'

'''SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SECURE_HSTS_SECONDS = 31536000
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.1/howto/static-files/

MEDIA_ROOT =  os.path.join(BASE_DIR, 'media') 
MEDIA_URL = '/media/'


PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
STATIC_ROOT  =   os.path.join(PROJECT_ROOT, 'staticfiles')
STATIC_URL = '/static/'
COMPRESS_ENABLED = os.environ.get('COMPRESS_ENABLED', False)
# Extra lookup directories for collectstatic to find static files
STATICFILES_DIRS = (
    os.path.join(PROJECT_ROOT, 'static'),
)

#  Add configuration for static files storage using whitenoise
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'

prod_db  =  dj_database_url.config(conn_max_age=500)
DATABASES['default'].update(prod_db)
'''

================================================
FILE: form/urls.py
================================================
"""form URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/3.1/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path, include
from django.contrib.staticfiles.storage import staticfiles_storage
from django.views.generic.base import RedirectView

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('index.urls')),
    path('favicon.ico', RedirectView.as_view(url = staticfiles_storage.url('favicon.ico')))
]


================================================
FILE: form/wsgi.py
================================================
"""
WSGI config for form project.

It exposes the WSGI callable as a module-level variable named ``application``.

For more information on this file, see
https://docs.djangoproject.com/en/3.1/howto/deployment/wsgi/
"""

import os

from django.core.wsgi import get_wsgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'form.settings')

application = get_wsgi_application()


================================================
FILE: index/__init__.py
================================================


================================================
FILE: index/admin.py
================================================
from django.contrib import admin

# Register your models here.


================================================
FILE: index/apps.py
================================================
from django.apps import AppConfig


class IndexConfig(AppConfig):
    name = 'index'


================================================
FILE: index/migrations/0001_initial.py
================================================
# Generated by Django 3.1.3 on 2020-11-28 13:29

from django.conf import settings
import django.contrib.auth.models
import django.contrib.auth.validators
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone


class Migration(migrations.Migration):

    initial = True

    dependencies = [
        ('auth', '0012_alter_user_first_name_max_length'),
    ]

    operations = [
        migrations.CreateModel(
            name='User',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('password', models.CharField(max_length=128, verbose_name='password')),
                ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
                ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
                ('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')),
                ('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')),
                ('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')),
                ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
                ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
                ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
                ('email', models.EmailField(max_length=254, unique=True)),
                ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')),
                ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')),
            ],
            options={
                'verbose_name': 'user',
                'verbose_name_plural': 'users',
                'abstract': False,
            },
            managers=[
                ('objects', django.contrib.auth.models.UserManager()),
            ],
        ),
        migrations.CreateModel(
            name='Answer',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('answer', models.CharField(max_length=5000)),
            ],
        ),
        migrations.CreateModel(
            name='Choices',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('choice', models.CharField(max_length=5000)),
                ('is_answer', models.BooleanField(default=False)),
            ],
        ),
        migrations.CreateModel(
            name='Form',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('code', models.CharField(max_length=30)),
                ('title', models.CharField(max_length=200)),
                ('description', models.CharField(blank=True, max_length=10000)),
                ('background_color', models.CharField(default='#d9efed', max_length=20)),
                ('text_color', models.CharField(default='#272124', max_length=20)),
                ('collect_email', models.BooleanField(default=False)),
                ('authenticated_responder', models.BooleanField(default=False)),
                ('edit_after_submit', models.BooleanField(default=False)),
                ('see_response', models.BooleanField(default=False)),
                ('confirmation_message', models.CharField(default='Your response has been recorded.', max_length=10000)),
                ('is_quiz', models.BooleanField(default=False)),
                ('allow_view_score', models.BooleanField(default=True)),
                ('createdAt', models.DateTimeField(auto_now_add=True)),
                ('updatedAt', models.DateTimeField(auto_now=True)),
                ('creator', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='creator', to=settings.AUTH_USER_MODEL)),
            ],
        ),
        migrations.CreateModel(
            name='Responses',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('response_code', models.CharField(max_length=20)),
                ('responder_ip', models.CharField(max_length=30)),
                ('responder_email', models.EmailField(max_length=254)),
                ('responder', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='responder', to=settings.AUTH_USER_MODEL)),
                ('response', models.ManyToManyField(related_name='response', to='index.Answer')),
                ('response_to', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='response_to', to='index.form')),
            ],
        ),
        migrations.CreateModel(
            name='Questions',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('question', models.CharField(max_length=10000)),
                ('question_type', models.CharField(max_length=20)),
                ('required', models.BooleanField(default=False)),
                ('answer_key', models.CharField(blank=True, max_length=5000)),
                ('score', models.IntegerField(blank=True, default=0)),
                ('feedback', models.CharField(max_length=5000, null=True)),
                ('choices', models.ManyToManyField(related_name='choices', to='index.Choices')),
            ],
        ),
        migrations.AddField(
            model_name='form',
            name='questions',
            field=models.ManyToManyField(related_name='questions', to='index.Questions'),
        ),
        migrations.AddField(
            model_name='answer',
            name='answer_to',
            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answer_to', to='index.questions'),
        ),
    ]


================================================
FILE: index/migrations/0002_auto_20201128_2040.py
================================================
# Generated by Django 3.1.3 on 2020-11-28 13:40

from django.db import migrations, models


class Migration(migrations.Migration):

    dependencies = [
        ('index', '0001_initial'),
    ]

    operations = [
        migrations.AlterField(
            model_name='responses',
            name='responder_email',
            field=models.EmailField(blank=True, max_length=254),
        ),
    ]


================================================
FILE: index/migrations/0003_remove_form_see_response.py
================================================
# Generated by Django 3.1.3 on 2020-11-28 14:58

from django.db import migrations


class Migration(migrations.Migration):

    dependencies = [
        ('index', '0002_auto_20201128_2040'),
    ]

    operations = [
        migrations.RemoveField(
            model_name='form',
            name='see_response',
        ),
    ]


================================================
FILE: index/migrations/__init__.py
================================================


================================================
FILE: index/models.py
================================================
from django.db import models
from django.contrib.auth.models import AbstractUser

# Create your models here.
class User(AbstractUser, models.Model):
    email = models.EmailField(unique = True)

class Choices(models.Model):
    choice = models.CharField(max_length=5000)
    is_answer = models.BooleanField(default=False)

class Questions(models.Model):
    question = models.CharField(max_length= 10000)
    question_type = models.CharField(max_length=20)
    required = models.BooleanField(default= False)
    answer_key = models.CharField(max_length = 5000, blank = True)
    score = models.IntegerField(blank = True, default=0)
    feedback = models.CharField(max_length = 5000, null = True)
    choices = models.ManyToManyField(Choices, related_name = "choices")

class Answer(models.Model):
    answer = models.CharField(max_length=5000)
    answer_to = models.ForeignKey(Questions, on_delete = models.CASCADE ,related_name = "answer_to")

class Form(models.Model):
    code = models.CharField(max_length=30)
    title = models.CharField(max_length=200)
    description = models.CharField(max_length=10000, blank = True)
    creator = models.ForeignKey(User, on_delete = models.CASCADE, related_name = "creator")
    background_color = models.CharField(max_length=20, default = "#d9efed")
    text_color = models.CharField(max_length=20, default="#272124")
    collect_email = models.BooleanField(default=False)
    authenticated_responder = models.BooleanField(default = False)
    edit_after_submit = models.BooleanField(default=False)
    confirmation_message = models.CharField(max_length = 10000, default = "Your response has been recorded.")
    is_quiz = models.BooleanField(default=False)
    allow_view_score = models.BooleanField(default= True)
    createdAt = models.DateTimeField(auto_now_add = True)
    updatedAt = models.DateTimeField(auto_now = True)
    questions = models.ManyToManyField(Questions, related_name = "questions")

class Responses(models.Model):
    response_code = models.CharField(max_length=20)
    response_to = models.ForeignKey(Form, on_delete = models.CASCADE, related_name = "response_to")
    responder_ip = models.CharField(max_length=30)
    responder = models.ForeignKey(User, on_delete = models.CASCADE, related_name = "responder", blank = True, null = True)
    responder_email = models.EmailField(blank = True)
    response = models.ManyToManyField(Answer, related_name = "response")

================================================
FILE: index/static/index/HurlUI.css
================================================
@import url("https://fonts.googleapis.com/css?family=Roboto+Condensed");
@import url("https://fonts.googleapis.com/css?family=Poppins");
@import url("https://fonts.googleapis.com/css?family=Montserrat");
@import url("https://fonts.googleapis.com/css?family=Times+New+Roman");
body{
	margin: 0;
	padding: 0;
	font-family: "Times New Roman","Roboto Condensed", "Poppins","Arial";
}

.center{
	text-align: center;
}

.link{
    color: #000;
    text-decoration: none;
    opacity: .7;
}
.link:hover{opacity: .4;}

.margin{
	margin: 20px;
}

.margin-top-bottom{
	margin: 20px 0;
}

.margin-left-right{
	margin: 0 20px;
}

.text-link{
	opacity: .8;
}

.text-link:hover{
	opacity: .4;
}
.container {
	padding-right: 15px;
	padding-left: 15px;
	margin-right: auto;
	margin-left: auto;
}
.container-fluid {
  	width: 100%;
}
[class*="col-"] {
  float: left;
}
.row{
	grid-row-gap: 5px;
	grid-column-gap: 5px;
	float: left;
}
.bg-dark, .btn-dark{
	background-color: #1c1e1f !important;
	color: #FFF !important;
}

.bg-light, .btn-light{
	background-color: #DAE0E2 !important;
	color: #000 !important;
}

.bg-black{
	background-color: #000 !important;
	color: #FFF !important;
}

.bg-white{
	background-color: #FFF !important;
	color: #000 !important;
}

body[theme="dark"]{
	background-color: #080808;
	color: #FFF;
}
body[theme="light"]{
	background-color: #F5F5F5;
	color: #000;
}
.text-dark{color: #1c1e1f !important;}
.text-light{color: #DAE0E2 !important;}
.text-danger{color: #E71C23 !important;}
.text-success{color: #6AB04A !important;}
.text-warning{color: #FFF222 !important;}
.text-blur{opacity: .7;}
.text-red{color : #e60000 !important;}
.text-darkblue{color : #000066 !important;}
.text-blue{color : #0000ff !important;}
.text-green{color: #00b300 !important;}
.text-darkgreen{color: #004d00 !important;}
.text-lightgreen{color: #00e600 !important;}
.text-orange{color: #ff9900 !important;}
.text-cyan{color: #33ffff !important;} 
.text-gray{color: #ccccb3 !important;}

.col-1 , .col-ex-1{width: 8.33%;}
.col-2 , .col-ex-2{width: 16.66%;}
.col-3 , .col-ex-3{width: 25%;}
.col-4 , .col-ex-4{width: 33.33%;}
.col-5 , .col-ex-5{width: 41.66%;}
.col-6 , .col-ex-6{width: 50%;}
.col-7 , .col-ex-7{width: 58.33%;}
.col-8 , .col-ex-8{width: 66.66%;}
.col-9 , .col-ex-9{width: 75%;}
.col-10, .col-ex-10 {width: 83.33%;}
.col-11, .col-ex-11 {width: 91.66%;}
.col-12, .col-ex-1 {width: 100%;}

.btn{
	padding: 10px;
	border: 1px solid black;
	border-radius: 5px;
	text-decoration: none;
	font-size: 1rem;
	color: black;
	font-family: "Poppins";
}
.btn-hover:hover{
	box-shadow: 5px 2px 8px;
	opacity: .7;
}
.btn-danger{background-color: #E71C23; color: #FFF;}
.btn-success{background-color: #6AB04A; color: #FFF;}
.btn-warning{background-color: #FFF222; color: #000;}

.box{
	padding: 10px;
	border: 1px solid #999;
	border-radius: 5px;
	width: -webkit-fill-available;
	width: -moz-available;
}

.box-image img, .box-image{
	width: 100%;
}
.box-title, .heading-title{
	font-weight: bold;
	text-align: center;
	font-family: "Montserrat";
	padding: 2px 5px;
	border-bottom: 0.5px solid #e6e6e6; 
}

.box-text{
	font-family: "Roboto Condensed";
}

.box-shadow{
	box-shadow: 3px 5px 11px;
}

.form-label, .text-label{
	font-family: "Poppins", "Arial";
	margin: 10px 0;
}

.form-group{
	margin: 16px 14px;
}

.form-control{
	color: black;
	border: 1px solid #bfbfbf;
	width: -webkit-fill-available;
	width: -moz-available;
	border-radius: 5px;
	padding: 8px;

}
.form-hover:hover{
	opacity: .7;
	box-shadow: 2px 2px 3px;
}
.navbar{
	margin: 0;
	padding: 0;
	overflow: hidden;
	background-color: white;
	width: 100%;
}

.nav-list{
	margin: 0;
	list-style-type: none;
}
.nav-logo, .nav-logo a{
	float: left;
	max-width: 200px;
	margin: 10px;
	text-decoration: none;
	color: black;
	font-size: 1.5rem;
}
.navbar .nav-item{
	display: block;
	text-align: center;
	padding: 14px 16px;
	font-size: 17px;
	float: right;
}

.navbar .nav-item a{
	text-decoration: none;
	color: black;
}
.navbar .nav-item a:hover{
	opacity: .7;
}

.nav-icon{
	display: none !important;
}

.fixed-top{
	top: 0px;
	position: fixed;
}

.fixed-bottom{
	bottom: 0;
	position: fixed;
}

.text-center{
	text-align: center;
}

footer, .footer{
	width: 100%;
	float: left;
}

.copyright{
	text-align: center;
	font-size: 20px;
	border-top: 1px solid;
	padding: 10px;
	background-color: #000;
	color: #FFF;
	margin: 0;
}

code{
	text-align: center;
	padding: 10px 20px;
	border-radius: 5px;
}

.img-frame{
	border: 1px solid #ddd;
	border-radius: 4px;
	padding: 5px;
}

.img-hover:hover{
	 opacity: .4;
}
table{
	width: 100%;
}

th{
	height: 40px;
}

td{padding: 8px;}
.table-border, .table-border table, .table-border th, .table-border tr, .table-border td{
	border: 1px solid;
}

.table-white-black tr:nth-child(even){background-color: #000; color: #FFF;}
.table-white-black tr:nth-child(odd){background-color: #FFF; color: #000;}
.table-black-white tr:nth-child(odd){background-color: #000; color: #FFF;}
.table-black-white tr:nth-child(even){background-color: #FFF; color: #000;}
@media only screen and (max-width: 600px){
	.nav-icon{
		display: block !important;
		position: absolute;
		right: 20px;
		top: 20px;
	}

	.nav-item{
		float: left;
		width: 100vw;
	}
	.nav-responsive{
		display: block !important;
	}
	.nav-list-responsive{
		display: none;
	}
}
@media only screen and (max-width: 600px) {
	[class*="col-"] {
		width: 100% !important;
	}
}
@media only screen and (max-width: 768px){
	.col-1{
		width: 16.66%;
	}
	.col-2{
		width: 25%;
	}
	.col-3, .col-4, .col-5, .col-6{
		width: 50%;
	}
	.col-7, .col-8, .col-9, .col-10, .col-11, .col-12{
		width: 100%;
	}
	[class*="col-ex-"]{
		width: 100%;
	}
}
@media only screen and (min-width: 768px) {
	.container {
		width: 750px;
	}
}
@media only screen and (min-width: 992px) {
	.container {
		width: 970px;
	}
}
@media only screen and (min-width: 1200px) {
	.container {
		width: 1170px;
	}
}

================================================
FILE: index/static/index/form.js
================================================
document.addEventListener("DOMContentLoaded", () => {
    const csrf = Cookies.get('csrftoken');
    document.body.style.backgroundColor =  document.querySelector("#bg-color").innerHTML;
    document.body.style.color =  document.querySelector("#text-color").innerHTML;
    document.querySelectorAll(".txt-clr").forEach(element => {
        element.style.color = document.querySelector("#text-color").innerHTML;
    })
    document.querySelectorAll(".input-form-title").forEach(title => {
        title.addEventListener("input", function(){
            fetch(`edit_title`, {
                method: "POST",
                headers: {'X-CSRFToken': csrf},
                body: JSON.stringify({
                    "title": this.value
                })

            })
            document.title = `${this.value} - Google Forms CLONE`
            document.querySelectorAll(".input-form-title").forEach(ele => {
                ele.value = this.value;
            })
        })
    })
    document.querySelector("#input-form-description").addEventListener("input", function(){
        fetch('edit_description', {
            method: "POST",
            headers: {'X-CSRFToken': csrf},
            body: JSON.stringify({
                "description": this.value
            })
        })
    })
    document.querySelectorAll(".textarea-adjust").forEach(tx => {
        tx.style.height = "auto";
        tx.style.height = (10 + tx.scrollHeight)+"px";
        tx.addEventListener('input', e => {
            tx.style.height = "auto";
            tx.style.height = (10 + tx.scrollHeight)+"px";
        })
    })
    document.querySelector("#customize-theme-btn").addEventListener('click', () => {
        document.querySelector("#customize-theme").style.display = "block";
        document.querySelector("#close-customize-theme").addEventListener('click', () => {
            document.querySelector("#customize-theme").style.display = "none";
        })
        window.onclick = e => {
            if(e.target == document.querySelector("#customize-theme")) document.querySelector("#customize-theme").style.display = "none";
        }
    })
    document.querySelector("#input-bg-color").addEventListener("input", function(){
        document.body.style.backgroundColor = this.value;
        fetch('edit_background_color', {
            method: "POST",
            headers: {'X-CSRFToken': csrf},
            body: JSON.stringify({
                "bgColor": this.value
            })
        })
    })
    document.querySelector("#input-text-color").addEventListener("input", function(){
        document.querySelectorAll(".txt-clr").forEach(element => {
            element.style.color = this.value;
        })
        fetch('edit_text_color', {
            method: "POST",
            headers: {'X-CSRFToken': csrf},
            body: JSON.stringify({
                "textColor": this.value
            })
        })
    })
    document.querySelectorAll(".open-setting").forEach(ele => {
        ele.addEventListener('click', () => {
            document.querySelector("#setting").style.display = "block";
        })
        document.querySelector("#close-setting").addEventListener('click', () => {
            document.querySelector("#setting").style.display = "none";
        })
        window.onclick = e => {
            if(e.target == document.querySelector("#setting")) document.querySelector("#setting").style.display = "none";
        }
    })
    document.querySelectorAll("#send-form-btn").forEach(btn => {
        btn.addEventListener("click", () => {
            document.querySelector("#send-form").style.display = "block";
        })
        document.querySelector("#close-send-form").addEventListener("click", () => {
            document.querySelector("#send-form").style.display = "none";
        })
        window.onclick = e => {
            if(e.target == document.querySelector("#send-form")) document.querySelector("#send-form").style.display = "none";
        }
    })
    document.querySelectorAll("[copy-btn]").forEach(btn => {
        btn.addEventListener("click", () => {
            var url = document.getElementById("copy-url");
            navigator.clipboard.writeText(url.value);
            document.querySelector("#send-form").style.display = "none";
        })
    })
    document.querySelector("#setting-form").addEventListener("submit", e => {
        e.preventDefault();
        fetch('edit_setting', {
            method: "POST",
            headers: {'X-CSRFToken': csrf},
            body: JSON.stringify({
                "collect_email": document.querySelector("#collect_email").checked,
                "is_quiz": document.querySelector("#is_quiz").checked,
                "authenticated_responder": document.querySelector("#authenticated_responder").checked,
                "confirmation_message": document.querySelector("#comfirmation_message").value,
                "edit_after_submit": document.querySelector("#edit_after_submit").checked,
                "allow_view_score": document.querySelector("#allow_view_score").checked,
            })
        })
        document.querySelector("#setting").style.display = "none";
        if(!document.querySelector("#collect_email").checked){
            if(document.querySelector(".collect-email")) document.querySelector(".collect-email").parentNode.removeChild(document.querySelector(".collect-email"))
        }else{
            if(!document.querySelector(".collect-email")){
                let collect_email = document.createElement("div");
                collect_email.classList.add("collect-email")
                collect_email.innerHTML = `<h3 class="question-title">Email address <span class="require-star">*</span></h3>
                <input type="text" autoComplete="off" aria-label="Valid email address" disabled dir = "auto" class="require-email-edit"
                placeholder = "Valid email address" />
                <p class="collect-email-desc">This form is collecting email addresses. <span class="open-setting">Change settings</span></p>`
                document.querySelector("#form-head").appendChild(collect_email)
            }
        }
        if(document.querySelector("#is_quiz").checked){
            if(!document.querySelector("#add-score")){
                let is_quiz = document.createElement('a')
                is_quiz.setAttribute("href", "score");
                is_quiz.setAttribute("id", "add-score");
                is_quiz.innerHTML = `<img src = "/static/Icon/score.png" id="add-score" class = "form-option-icon" title = "Add score" alt = "Score icon" />`;
                document.querySelector(".question-options").appendChild(is_quiz)
            }
            if(!document.querySelector(".score")){
                let quiz_nav = document.createElement("span");
                quiz_nav.classList.add("col-4");
                quiz_nav.classList.add("navigation");
                quiz_nav.classList.add('score');
                quiz_nav.innerHTML =   `<a href = "score" class="link">Scores</a>`;
                [...document.querySelector(".form-navigation").children].forEach(element => {
                    element.classList.remove("col-6")
                    element.classList.add('col-4')
                })
                document.querySelector(".form-navigation").insertBefore(quiz_nav, document.querySelector(".form-navigation").childNodes[2])
            }
        }else{
            if(document.querySelector("#add-score")) document.querySelector("#add-score").parentNode.removeChild(document.querySelector("#add-score"))
            if(document.querySelector(".score")){
                [...document.querySelector(".form-navigation").children].forEach(element => {
                    element.classList.remove("col-4")
                    element.classList.add('col-6')
                })
                document.querySelector(".score").parentNode.removeChild(document.querySelector(".score"))
            }
        }
    })
    document.querySelector("#delete-form").addEventListener("submit", e => {
        e.preventDefault();
        if(window.confirm("Are you sure? This action CANNOT be undone.")){
            fetch('delete', {
                method: "DELETE",
                headers: {'X-CSRFToken': csrf}
            })
            .then(() => window.location = "/")
        }
    })
    const editQuestion = () => {
        document.querySelectorAll(".input-question").forEach(question => {
            question.addEventListener('input', function(){
                let question_type;
                let required;
                document.querySelectorAll(".input-question-type").forEach(qp => {
                    if(qp.dataset.id === this.dataset.id) question_type = qp.value
                })
                document.querySelectorAll('.required-checkbox').forEach(rc => {
                    if(rc.dataset.id === this.dataset.id) required = rc.checked;
                })
                fetch('edit_question', {
                    method: "POST",
                    headers: {'X-CSRFToken': csrf},
                    body: JSON.stringify({
                        id: this.dataset.id,
                        question: this.value,
                        question_type: question_type,
                        required: required
                    })
                })
            })
        })
    }
    editQuestion();
    
    const editRequire = () => {
        document.querySelectorAll(".required-checkbox").forEach(checkbox => {
            checkbox.addEventListener('input', function(){
                let question;
                let question_type;
                document.querySelectorAll(".input-question-type").forEach(qp => {
                    if(qp.dataset.id === this.dataset.id) question_type = qp.value
                })
                document.querySelectorAll('.input-question').forEach(q => {
                    if(q.dataset.id === this.dataset.id) question = q.value
                })
                fetch('edit_question', {
                    method: "POST",
                    headers: {'X-CSRFToken': csrf},
                    body: JSON.stringify({
                        id: this.dataset.id,
                        question: question,
                        question_type: question_type,
                        required: this.checked
                    })
                })
            })
        })
    }
    editRequire()
    const editChoice = () => {
        document.querySelectorAll(".edit-choice").forEach(choice => {
            choice.addEventListener("input", function(){
                fetch('edit_choice', {
                    method: "POST",
                    headers: {'X-CSRFToken': csrf},
                    body: JSON.stringify({
                        "id": this.dataset.id,
                        "choice": this.value
                    })
                })
            })
        })
    }
    editChoice()
    const removeOption = () => {
        document.querySelectorAll(".remove-option").forEach(ele => {
            ele.addEventListener("click",function(){
                fetch('remove_choice', {
                    method: "POST",
                    headers: {'X-CSRFToken': csrf},
                    body: JSON.stringify({
                        "id": this.dataset.id
                    })
                })
                .then(() => {
                    this.parentNode.parentNode.removeChild(this.parentNode)
                })
            })
        })
    }
    removeOption()
    const addOption = () => {
        document.querySelectorAll(".add-option").forEach(question =>{
            question.addEventListener("click", function(){
                fetch('add_choice', {
                    method: "POST",
                    headers: {'X-CSRFToken': csrf},
                    body: JSON.stringify({
                        "question": this.dataset.question
                    })
                })
                .then(response => response.json())
                .then(result => {
                    let element = document.createElement("div");
                    element.classList.add('choice');
                    if(this.dataset.type === "multiple choice"){
                        element.innerHTML = `<input type="radio" id="${result["id"]}" disabled>
                        <label for="${result["id"]}">
                            <input type="text" value="${result["choice"]}" class="edit-choice" data-id="${result["id"]}">
                        </label>
                        <span class="remove-option" title = "Remove" data-id="${result["id"]}">&times;</span>`;
                    }else if(this.dataset.type === "checkbox"){
                        element.innerHTML = `<input type="checkbox" id="${result["id"]}" disabled>
                        <label for="${result["id"]}">
                            <input type="text" value="${result["choice"]}" class="edit-choice" data-id="${result["id"]}">
                        </label>
                        <span class="remove-option" title = "Remove" data-id="${result["id"]}">&times;</span>`;
                    }
                    document.querySelectorAll(".choices").forEach(choices => {
                        if(choices.dataset.id === this.dataset.question){
                            choices.insertBefore(element, choices.childNodes[choices.childNodes.length -2]);
                            editChoice()
                            removeOption()
                        }
                    });
                })
            })
        })
    }
    addOption()
    const deleteQuestion = () => {
        document.querySelectorAll(".delete-question").forEach(question => {
            question.addEventListener("click", function(){
                fetch(`delete_question/${this.dataset.id}`, {
                    method: "DELETE",
                    headers: {'X-CSRFToken': csrf},
                })
                .then(() => {
                    document.querySelectorAll(".question").forEach(q =>{
                        if(q.dataset.id === this.dataset.id){
                            q.parentNode.removeChild(q)
                        }
                    })
                })
            })
        })
    }
    deleteQuestion()
    const changeType = () => {
        document.querySelectorAll(".input-question-type").forEach(ele => {
            ele.addEventListener('input', function(){
                let required;
                let question;
                document.querySelectorAll('.required-checkbox').forEach(rc => {
                    if(rc.dataset.id === this.dataset.id) required = rc.checked;
                })
                document.querySelectorAll('.input-question').forEach(q => {
                    if(q.dataset.id === this.dataset.id) question = q.value
                })
                fetch('edit_question', {
                    method: "POST",
                    headers: {'X-CSRFToken': csrf},
                    body: JSON.stringify({
                        id: this.dataset.id,
                        question: question,
                        question_type: this.value,
                        required: required
                    })
                })

                if(this.dataset.origin_type === "multiple choice" || this.dataset.origin_type === "checkbox"){
                    document.querySelectorAll(".choices").forEach(choicesElement => {
                        if(choicesElement.dataset.id === this.dataset.id){
                            if(this.value === "multiple choice" || this.value === "checkbox"){
                                fetch(`get_choice/${this.dataset.id}`, {
                                    method: "GET"
                                })
                                .then(response => response.json())
                                .then(result => {
                                    let ele = document.createElement("div");
                                    ele.classList.add('choices');
                                    ele.setAttribute("data-id", result["question_id"])
                                    let choices = '';
                                    if(this.value === "multiple choice"){
                                        for(let i in result["choices"]){
                                            if(i){ choices += `<div class="choice">
                                            <input type="radio" id="${result["choices"][i].id}" disabled>
                                            <label for="${result["choices"][i].id}">
                                                <input type="text" data-id="${result["choices"][i].id}" class="edit-choice" value="${result["choices"][i].choice}">
                                            </label>
                                            <span class="remove-option" title="Remove" data-id="${result["choices"][i].id}">&times;</span></div>`}
                                        }
                                    }else if(this.value === "checkbox"){
                                        for(let i in result["choices"]){
                                            if(i){choices += `<div class="choice">
                                            <input type="checkbox" id="${result["choices"][i].id}" disabled>
                                            <label for="${result["choices"][i].id}">
                                                <input type="text" data-id="${result["choices"][i].id}" class="edit-choice" value="${result["choices"][i].choice}">
                                            </label>
                                            <span class="remove-option" title="Remove" data-id="${result["choices"][i].id}">&times;</span></div>`}
                                        }
                                    }
                                    ele.innerHTML = `<div class="choice">${choices}</div>
                                    <div class="choice">
                                        <input type = "radio" id = "add-choice" disabled />
                                        <label for = "add-choice" class="add-option" id="add-option" data-question="${result["question_id"]}"
                                        data-type = "${this.value}">Add option</label>
                                    </div>`;
                                    choicesElement.parentNode.replaceChild(ele, choicesElement);
                                    editChoice()
                                    removeOption()
                                    changeType()
                                    editQuestion()
                                    editRequire()
                                    addOption()
                                    deleteQuestion()
                                })
                            }else{
                                if(this.value === "short"){
                                    choicesElement.parentNode.removeChild(choicesElement)
                                    let ele = document.createElement("div");
                                    ele.innerHTML = `<div class="answers" data-id="${this.dataset.id}">
                                    <input type ="text" class="short-answer" disabled placeholder="Short answer text" />
                                </div>`
                                    this.parentNode.insertBefore(ele, this.parentNode.childNodes[4])
                                }else if(this.value === "paragraph"){
                                    choicesElement.parentNode.removeChild(choicesElement)
                                    let ele = document.createElement("div");
                                    ele.innerHTML = `<div class="answers" data-id="${this.dataset.id}">
                                    <textarea class="long-answer" disabled placeholder="Long answer text" ></textarea>
                                </div>`
                                    this.parentNode.insertBefore(ele, this.parentNode.childNodes[4])
                                }
                            }
                        }
                    })
                }else{
                    document.querySelectorAll(".question-box").forEach(question => {
                        document.querySelectorAll(".answers").forEach(answer => {
                            if(answer.dataset.id === this.dataset.id){
                                answer.parentNode.removeChild(answer)
                            }
                        })
                        if((this.value === "multiple choice" || this.value === "checkbox") && question.dataset.id === this.dataset.id){
                            fetch(`get_choice/${this.dataset.id}`, {
                                method: "GET"
                            })
                            .then(response => response.json())
                            .then(result => {
                                let ele = document.createElement("div");
                                ele.classList.add('choices');
                                ele.setAttribute("data-id", result["question_id"])
                                let choices = '';
                                if(this.value === "multiple choice"){
                                    for(let i in result["choices"]){
                                        if(i){ choices += `<div class="choice">
                                        <input type="radio" id="${result["choices"][i].id}" disabled>
                                        <label for="${result["choices"][i].id}">
                                            <input type="text" data-id="${result["choices"][i].id}" class="edit-choice" value="${result["choices"][i].choice}">
                                        </label>
                                        <span class="remove-option" title="Remove" data-id="${result["choices"][i].id}">&times;</span></div>`}
                                    }
                                }else if(this.value === "checkbox"){
                                    for(let i in result["choices"]){
                                        if(i){choices += `<div class="choice">
                                        <input type="checkbox" id="${result["choices"][i].id}" disabled>
                                        <label for="${result["choices"][i].id}">
                                            <input type="text" data-id="${result["choices"][i].id}" class="edit-choice" value="${result["choices"][i].choice}">
                                        </label>
                                        <span class="remove-option" title="Remove" data-id="${result["choices"][i].id}">&times;</span></div>`}
                                    }
                                }
                                ele.innerHTML = `<div class="choice">${choices}</div>
                                <div class="choice">
                                    <input type = "radio" id = "add-choice" disabled />
                                    <label for = "add-choice" class="add-option" id="add-option" data-question="${result["question_id"]}"
                                    data-type = "${this.value}">Add option</label>
                                </div>`;
                                question.insertBefore(ele, question.childNodes[4])
                                editChoice()
                                removeOption()
                                changeType()
                                editQuestion()
                                editRequire()
                                addOption()
                                deleteQuestion()
                            })
                        }else{
                            if(this.value === "short"){
                                let ele = document.createElement("div");
                                ele.innerHTML = `<div class="answers" data-id="${this.dataset.id}">
                                <input type ="text" class="short-answer" disabled placeholder="Short answer text" />
                            </div>`
                                this.parentNode.insertBefore(ele, this.parentNode.childNodes[4])
                            }else if(this.value === "paragraph"){
                                let ele = document.createElement("div");
                                ele.innerHTML = `<div class="answers" data-id="${this.dataset.id}">
                                <textarea class="long-answer" disabled placeholder="Long answer text" ></textarea>
                            </div>`
                                this.parentNode.insertBefore(ele, this.parentNode.childNodes[4])
                            }
                        }
                    })
                }
                this.setAttribute("data-origin_type", this.value);
            })
        })
    }
    changeType()
    document.querySelector("#add-question").addEventListener("click", () => {
        fetch('add_question', {
            method: "POST",
            headers: {'X-CSRFToken': csrf},
            body: JSON.stringify({})
        })
        .then(response => response.json())
        .then(result => {
            let ele = document.createElement('div')
            ele.classList.add('margin-top-bottom');
            ele.classList.add('box');
            ele.classList.add('question-box');
            ele.classList.add('question');
            ele.setAttribute("data-id", result["question"].id)
            ele.innerHTML = `
            <input type="text" data-id="${result["question"].id}" class="question-title edit-on-click input-question" value="${result["question"].question}">
            <select class="question-type-select input-question-type" data-id="${result["question"].id}" data-origin_type = "${result["question"].question_type}">
                <option value="short">Short answer</option>
                <option value="paragraph">Paragraph</option>
                <option value="multiple choice" selected>Multiple choice</option>
                <option value="checkbox">Checkbox</option>
            </select>
            <div class="choices" data-id="${result["question"].id}">
                <div class="choice">
                    <input type="radio" id="${result["choices"].id}" disabled>
                    <label for="${result["choices"].id}">
                        <input type="text" value="${result["choices"].choice}" class="edit-choice" data-id="${result["choices"].id}">
                    </label>
                    <span class="remove-option" title = "Remove" data-id="${result["choices"].id}">&times;</span>
                </div>
                <div class="choice">
                    <input type = "radio" id = "add-choice" disabled />
                    <label for = "add-choice" class="add-option" id="add-option" data-question="${result["question"].id}" 
                    data-type = "${result["question"].question_type}">Add option</label>
                </div>
            </div>
            <div class="choice-option">
                <input type="checkbox" class="required-checkbox" id="${result["question"].id}" data-id="${result["question"].id}">
                <label for="${result["question"].id}" class="required">Required</label>
                <div class="float-right">
                    <img src="/static/Icon/dustbin.png" alt="Delete question icon" class="question-option-icon delete-question" title="Delete question"
                    data-id="${result["question"].id}">
                </div>
            </div>
            `;
            document.querySelector(".container").appendChild(ele);
            editChoice()
            removeOption()
            changeType()
            editQuestion()
            editRequire()
            addOption()
            deleteQuestion()
        })
    })
})

================================================
FILE: index/static/index/index.js
================================================
document.addEventListener("DOMContentLoaded", () => {
    document.querySelector("#nav-ham").addEventListener("click", () => {
        document.querySelector("#sidebar").style.width = "250px";
    })
    document.querySelector("#close-sidebar").addEventListener('click', () => {
        document.querySelector("#sidebar").style.width = "0px";
    })
    document.querySelector("#create-blank-form").addEventListener("click", () => {
        const csrf = Cookies.get('csrftoken');
        fetch('/form/create', {
            method: "POST",
            headers: {'X-CSRFToken': csrf},
            body: JSON.stringify({
                title: "Untitled Form"
            })
        })
        .then(response => response.json())
        .then(result => {
            window.location = `/form/${result.code}/edit`
        })
    })
    document.querySelector("#create-contact-form").addEventListener("click", () => {
        const csrf = Cookies.get('csrftoken');
        fetch('/form/create/contact', {
            method: "POST",
            headers: {'X-CSRFToken': csrf},
            body: JSON.stringify({})
        })
        .then(response => response.json())
        .then(result => {
            window.location = `/form/${result.code}/edit`
        })
    })
    document.querySelector("#create-customer-feedback").addEventListener("click", () => {
        const csrf = Cookies.get('csrftoken');
        fetch('/form/create/feedback', {
            method: "POST",
            headers: {'X-CSRFToken': csrf},
            body: JSON.stringify({})
        })
        .then(response => response.json())
        .then(result => {
            window.location = `/form/${result.code}/edit`
        })
    })
    document.querySelector("#create-event-registration").addEventListener("click", () => {
        const csrf = Cookies.get('csrftoken');
        fetch('/form/create/event', {
            method: "POST",
            headers: {'X-CSRFToken': csrf},
            body: JSON.stringify({})
        })
        .then(response => response.json())
        .then(result => {
            window.location = `/form/${result.code}/edit`
        })
    })
})

================================================
FILE: index/static/index/response.js
================================================
document.addEventListener("DOMContentLoaded", () => {
    document.body.style.backgroundColor =  document.querySelector("#bg-color").innerHTML;
    document.body.style.color =  document.querySelector("#text-color").innerHTML;
    document.querySelectorAll(".txtClr").forEach(element => {
        element.style.color = document.querySelector("#text-color").innerHTML;
    })
})

================================================
FILE: index/static/index/responses.js
================================================
document.addEventListener("DOMContentLoaded", () => {
    const csrf = Cookies.get('csrftoken');
    document.body.style.backgroundColor =  document.querySelector("#bg-color").innerHTML;
    document.body.style.color =  document.querySelector("#text-color").innerHTML;
    document.querySelector("#customize-theme-btn").addEventListener('click', () => {
        document.querySelector("#customize-theme").style.display = "block";
        document.querySelector("#close-customize-theme").addEventListener('click', () => {
            document.querySelector("#customize-theme").style.display = "none";
        })
        window.onclick = e => {
            if(e.target == document.querySelector("#customize-theme")) document.querySelector("#customize-theme").style.display = "none";
        }
    })
    document.querySelector("#input-bg-color").addEventListener("input", function(){
        document.body.style.backgroundColor = this.value;
        fetch('edit_background_color', {
            method: "POST",
            headers: {'X-CSRFToken': csrf},
            body: JSON.stringify({
                "bgColor": this.value
            })
        })
    })
    document.querySelector("#input-text-color").addEventListener("input", function(){
        document.querySelectorAll(".txt-clr").forEach(element => {
            element.style.color = this.value;
        })
        fetch('edit_text_color', {
            method: "POST",
            headers: {'X-CSRFToken': csrf},
            body: JSON.stringify({
                "textColor": this.value
            })
        })
    })
    document.querySelectorAll(".open-setting").forEach(ele => {
        ele.addEventListener('click', () => {
            document.querySelector("#setting").style.display = "block";
        })
        document.querySelector("#close-setting").addEventListener('click', () => {
            document.querySelector("#setting").style.display = "none";
        })
        window.onclick = e => {
            if(e.target == document.querySelector("#setting")) document.querySelector("#setting").style.display = "none";
        }
    })
    document.querySelector("#delete-form").addEventListener("submit", e => {
        e.preventDefault();
        if(window.confirm("Are you sure? This action CANNOT be undone.")){
            fetch('delete', {
                method: "DELETE",
                headers: {'X-CSRFToken': csrf}
            })
            .then(() => window.location = "/")
        }
    })
    document.querySelectorAll("#send-form-btn").forEach(btn => {
        btn.addEventListener("click", () => {
            document.querySelector("#send-form").style.display = "block";
        })
        document.querySelector("#close-send-form").addEventListener("click", () => {
            document.querySelector("#send-form").style.display = "none";
        })
        window.onclick = e => {
            if(e.target == document.querySelector("#send-form")) document.querySelector("#send-form").style.display = "none";
        }
    })
    document.querySelectorAll("[copy-btn]").forEach(btn => {
        btn.addEventListener("click", () => {
            var url = document.getElementById("copy-url");
            navigator.clipboard.writeText(url.value);
            document.querySelector("#send-form").style.display = "none";
        })
    })
    document.querySelector("#setting-form").addEventListener("submit", e => {
        e.preventDefault();
        fetch('edit_setting', {
            method: "POST",
            headers: {'X-CSRFToken': csrf},
            body: JSON.stringify({
                "collect_email": document.querySelector("#collect_email").checked,
                "is_quiz": document.querySelector("#is_quiz").checked,
                "authenticated_responder": document.querySelector("#authenticated_responder").checked,
                "confirmation_message": document.querySelector("#comfirmation_message").value,
                "edit_after_submit": document.querySelector("#edit_after_submit").checked,
                "allow_view_score": document.querySelector("#allow_view_score").checked
            })
        })
        document.querySelector("#setting").style.display = "none";
        if(!document.querySelector("#collect_email").checked){
            if(document.querySelector(".collect-email")) document.querySelector(".collect-email").parentNode.removeChild(document.querySelector(".collect-email"))
        }else{
            if(!document.querySelector(".collect-email")){
                let collect_email = document.createElement("div");
                collect_email.classList.add("collect-email")
                collect_email.innerHTML = `<h3 class="question-title">Email address <span class="require-star">*</span></h3>
                <input type="text" autoComplete="off" aria-label="Valid email address" disabled dir = "auto" class="require-email-edit"
                placeholder = "Valid email address" />
                <p class="collect-email-desc">This form is collecting email addresses. <span class="open-setting">Change settings</span></p>`
                document.querySelector("#form-head").appendChild(collect_email)
            }
        }
        if(document.querySelector("#is_quiz").checked){
            if(!document.querySelector("#add-score")){
                let is_quiz = document.createElement('a')
                is_quiz.setAttribute("href", "score");
                is_quiz.setAttribute("id", "add-score");
                is_quiz.innerHTML = `<img src = "/static/Icon/score.png" id="add-score" class = "form-option-icon" title = "Add score" alt = "Score icon" />`;
                document.querySelector(".question-options").appendChild(is_quiz)
            }
            if(!document.querySelector(".score")){
                let quiz_nav = document.createElement("span");
                quiz_nav.classList.add("col-4");
                quiz_nav.classList.add("navigation");
                quiz_nav.classList.add('score');
                quiz_nav.innerHTML =   `<a href = "score" class="link">Scores</a>`;
                [...document.querySelector(".form-navigation").children].forEach(element => {
                    element.classList.remove("col-6")
                    element.classList.add('col-4')
                })
                document.querySelector(".form-navigation").insertBefore(quiz_nav, document.querySelector(".form-navigation").childNodes[2])
            }
        }else{
            if(document.querySelector("#add-score")) document.querySelector("#add-score").parentNode.removeChild(document.querySelector("#add-score"))
            if(document.querySelector(".score")){
                [...document.querySelector(".form-navigation").children].forEach(element => {
                    element.classList.remove("col-4")
                    element.classList.add('col-6')
                })
                document.querySelector(".score").parentNode.removeChild(document.querySelector(".score"))
            }
        }
    })
    document.querySelectorAll(".textarea-adjust").forEach(tx => {
        tx.style.height = "auto";
        tx.style.height = (10 + tx.scrollHeight)+"px";
        tx.addEventListener('input', e => {
            tx.style.height = "auto";
            tx.style.height = (10 + tx.scrollHeight)+"px";
        })
    })
    if(document.querySelector("#delete-responses")){
        document.querySelector("#delete-responses").addEventListener("click", () => {
            if(window.confirm("Are you sure? This action CANNOT be undone.")){
                fetch('responses/delete', {
                    method: "DELETE",
                    headers: {'X-CSRFToken': csrf}
                })
                .then(() => {
                    let ele = document.createElement("div");
                    ele.classList.add('margin-top-bottom');
                    ele.classList.add('box');
                    ele.classList.add('question-box');
                    ele.innerHTML = '<h1 class="response-title">0 responses</h1>';
                    document.querySelector("#responses").parentNode.replaceChild(ele, document.querySelector("#responses"))
                })
            }
        })
    }
})

================================================
FILE: index/static/index/score.js
================================================
document.addEventListener("DOMContentLoaded", () => {
    const csrf = Cookies.get('csrftoken');
    document.body.style.backgroundColor =  document.querySelector("#bg-color").innerHTML;
    document.body.style.color =  document.querySelector("#text-color").innerHTML;
    document.querySelector("#customize-theme-btn").addEventListener('click', () => {
        document.querySelector("#customize-theme").style.display = "block";
        document.querySelector("#close-customize-theme").addEventListener('click', () => {
            document.querySelector("#customize-theme").style.display = "none";
        })
        window.onclick = e => {
            if(e.target == document.querySelector("#customize-theme")) document.querySelector("#customize-theme").style.display = "none";
        }
    })
    document.querySelector("#input-bg-color").addEventListener("input", function(){
        document.body.style.backgroundColor = this.value;
        fetch('edit_background_color', {
            method: "POST",
            headers: {'X-CSRFToken': csrf},
            body: JSON.stringify({
                "bgColor": this.value
            })
        })
    })
    document.querySelector("#input-text-color").addEventListener("input", function(){
        document.querySelectorAll(".txt-clr").forEach(element => {
            element.style.color = this.value;
        })
        fetch('edit_text_color', {
            method: "POST",
            headers: {'X-CSRFToken': csrf},
            body: JSON.stringify({
                "textColor": this.value
            })
        })
    })
    document.querySelectorAll(".open-setting").forEach(ele => {
        ele.addEventListener('click', () => {
            document.querySelector("#setting").style.display = "block";
        })
        document.querySelector("#close-setting").addEventListener('click', () => {
            document.querySelector("#setting").style.display = "none";
        })
        window.onclick = e => {
            if(e.target == document.querySelector("#setting")) document.querySelector("#setting").style.display = "none";
        }
    })
    document.querySelector("#delete-form").addEventListener("submit", e => {
        e.preventDefault();
        if(window.confirm("Are you sure? This action CANNOT be undone.")){
            fetch('delete', {
                method: "DELETE",
                headers: {'X-CSRFToken': csrf}
            })
            .then(() => window.location = "/")
        }
    })
    document.querySelectorAll("#send-form-btn").forEach(btn => {
        btn.addEventListener("click", () => {
            document.querySelector("#send-form").style.display = "block";
        })
        document.querySelector("#close-send-form").addEventListener("click", () => {
            document.querySelector("#send-form").style.display = "none";
        })
        window.onclick = e => {
            if(e.target == document.querySelector("#send-form")) document.querySelector("#send-form").style.display = "none";
        }
    })
    document.querySelectorAll("[copy-btn]").forEach(btn => {
        btn.addEventListener("click", () => {
            var url = document.getElementById("copy-url");
            navigator.clipboard.writeText(url.value);
            document.querySelector("#send-form").style.display = "none";
        })
    })
    document.querySelector("#setting-form").addEventListener("submit", e => {
        e.preventDefault();
        fetch('edit_setting', {
            method: "POST",
            headers: {'X-CSRFToken': csrf},
            body: JSON.stringify({
                "collect_email": document.querySelector("#collect_email").checked,
                "is_quiz": document.querySelector("#is_quiz").checked,
                "authenticated_responder": document.querySelector("#authenticated_responder").checked,
                "confirmation_message": document.querySelector("#comfirmation_message").value,
                "edit_after_submit": document.querySelector("#edit_after_submit").checked,
                "allow_view_score": document.querySelector("#allow_view_score").checked
            })
        })
        document.querySelector("#setting").style.display = "none";
        if(!document.querySelector("#collect_email").checked){
            if(document.querySelector(".collect-email")) document.querySelector(".collect-email").parentNode.removeChild(document.querySelector(".collect-email"))
        }else{
            if(!document.querySelector(".collect-email")){
                let collect_email = document.createElement("div");
                collect_email.classList.add("collect-email")
                collect_email.innerHTML = `<h3 class="question-title">Email address <span class="require-star">*</span></h3>
                <input type="text" autoComplete="off" aria-label="Valid email address" disabled dir = "auto" class="require-email-edit"
                placeholder = "Valid email address" />
                <p class="collect-email-desc">This form is collecting email addresses. <span class="open-setting">Change settings</span></p>`
                document.querySelector("#form-head").appendChild(collect_email)
            }
        }
        if(document.querySelector("#is_quiz").checked){
            if(!document.querySelector("#add-score")){
                let is_quiz = document.createElement('a')
                is_quiz.setAttribute("href", "/");
                is_quiz.setAttribute("id", "add-score");
                is_quiz.innerHTML = `<img src = "/static/Icon/score.png" id="add-score" class = "form-option-icon" title = "Add score" alt = "Score icon" />`;
                document.querySelector(".question-options").appendChild(is_quiz)
            }
        }else{
            if(document.querySelector("#add-score")){
                document.querySelector("#add-score").parentNode.removeChild(document.querySelector("#add-score"))
            }
        }
    })
    document.querySelectorAll(".textarea-adjust").forEach(tx => {
        tx.style.height = "auto";
        tx.style.height = (10 + tx.scrollHeight)+"px";
        tx.addEventListener('input', e => {
            tx.style.height = "auto";
            tx.style.height = (10 + tx.scrollHeight)+"px";
        })
    })
    document.querySelectorAll(".input-score").forEach(element => {
        element.addEventListener("input", function(){
            fetch('edit_score', {
                method: "POST",
                headers: {'X-CSRFToken': csrf},
                body: JSON.stringify({
                    question_id: this.dataset.id,
                    score: this.value
                })
            })
        })
    })
    document.querySelectorAll("[answer-key]").forEach(element => {
        element.addEventListener("input", function(){
            if(this.dataset.question_type === "multiple choice"){
                fetch('answer_key', {
                    method: "POST",
                    headers: {'X-CSRFToken': csrf},
                    body: JSON.stringify({
                        "question_id": this.dataset.id,
                        "answer_key": document.querySelector(`input[name="${this.name}"]:checked`).value
                    })
                })
            }else if(this.dataset.question_type === "checkbox"){
                answers = []
                document.getElementsByName(this.name).forEach(element => {
                    if(element.checked) answers.push(element.value)
                })
                fetch('answer_key', {
                    method: "POST",
                    headers: {'X-CSRFToken': csrf},
                    body: JSON.stringify({
                        "question_id": this.dataset.id,
                        "answer_key": answers
                    })
                })
            }
            else{
                fetch('answer_key', {
                    method: "POST",
                    headers: {'X-CSRFToken': csrf},
                    body: JSON.stringify({
                        "question_id": this.dataset.id,
                        "answer_key": this.value
                    })
                })
            }
        })
    })
    document.getElementsByName('feedback').forEach(element => {
        element.addEventListener("input", function(){
            fetch('feedback', {
                method: "POST",
                headers: {'X-CSRFToken': csrf},
                body: JSON.stringify({
                    "question_id": this.dataset.id,
                    "feedback": this.value
                })
            })
        })
    })
})

================================================
FILE: index/static/index/style.css
================================================
@import url("https://fonts.googleapis.com/css?family=Permanent+Marker");
@import url("https://fonts.googleapis.com/css?family=Product+Sans");
@import url("https://fonts.googleapis.com/css?family=Google+Sans");

body{
    scroll-behavior: smooth;
}

.form-error{
    font-family: "Permanent Marker";
    color: red;
}

.form-icon{
    width: 40px;
    margin-bottom: 0.5rem;
}

.topnav{
    float: left;
    width: 100vw;
}

.navbar-icon{
    float: left;
}
.nav-text{
    float: left;
    position: relative;
    vertical-align: middle;
    margin-top: 0.75rem;
    font-family: "Product Sans";
    color: #5f6368;
    padding-left: 1rem;
}

.nav-link{
    color: #000;
    text-decoration: none;
}

.nav-effect{box-shadow: 0 2px 30px -2px rgba(0,0,0,.2);}

.float-right{
    float: right;
}

.logout-icon{
    width: 40px;
    cursor: pointer;
}

.nav-padding{
    padding: 10px 20px 10px;
}
.sidebar{
    height: 100%;
    width: 0;
    position: fixed;
    z-index: 5;
    top: 0;
    left: 0;
    overflow-x: hidden;
    transition: 0.5s;
    background-color: #FFF;
    box-shadow: 10px 0 5px -2px #888;
}

.nav-ham{
    float: left;
    font-size: 1.8rem;
    position: relative;
    vertical-align: middle;
    margin-right: 1rem;
    cursor: pointer;
}

.close-sidebar{
    position: absolute;
    top: 0;
    right: 25px;
    font-size: 36px;
    margin-left: 50px;
    cursor: pointer;
}

.sidebar-content{
    margin: 20px
}

.sidebar-title{
    margin-top: 50px;
    font-family: "Google Sans";
    font-size: 1.3rem;
    border-bottom: 1px solid #888;
    text-align: center;
    cursor: pointer;
}

.sidebar-title-link{
    text-decoration: none;
    color: #414244;
}

.github-icon{
    width: 1.3rem;
}

.create-form{
    background-color: #f1f3f4;
    width: 100vw;
    float: left;
}

.forms-label{
    font-family: "Google Sans";
    margin: 10px 10px 5px 10px;
}

.form-template-box{
    margin: 5px 30px 10px 0;
    float: left;
}

.form-template-box img{
    width: 10em;
    height: 7em;
    float: left;
}

.form-template-box:hover{
    border: 1px solid black;
}

.form-box{
    width: 250px;
    border: 1px solid rgb(182, 179, 179);
    padding: 5px;
    cursor: pointer;
    margin: 10px;
    position: relative;
}

.form-box:hover{
    border: 1px solid darkblue;
}

.form-list{
    float: left;
    margin-top: 20px;
}

.form-list-title{
    align-items: flex-end;
    display: flex;
    flex-direction: row;
    position: relative;
}

.form-list-title-text{
    text-align: left;
    overflow: hidden;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 1;
    text-overflow: ellipsis;
    font-family: "Google Sans";
    margin: 2.5px;
}

.form-list-timestamp{
    margin: 2.5px ;
    color: gray;
}

.form-list-link{
    color: #000000;
    text-decoration: none;
    float: left;
}

.error-page{
    text-align: center;
    font-family: "Roboto Condensed";
}

.form-topnav{
    padding: 15px;
    overflow: hidden;
    background-color: #fff;
}

.nav-form-title{
    width: 300px;
    overflow: hidden;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 1;
    text-overflow: ellipsis;
}

.edit-on-click{
    border: none;
    font-size: 1.2rem;
    transition: 1s;
    overflow-y: hidden;
}

.edit-on-click:focus{
    outline: none !important;
    border-bottom: 1px solid #202124;
}

.nav-form-menu-icon{
    width: 1.5rem;
    margin: 10px 15px;
    cursor: pointer;
    float: left;
}

.send-form-btn{
    position: relative;
    background-color: #673ab7;
    color: #ddd;
    font-size: 1rem;
    font-family: "Google Sans";
    vertical-align: middle;
    border: 1px solid #ddd;
    padding: 10px 20px;
    float: left;
    margin: 0.2px 15px;
}

.question-box{
    background-color: #FFF;
}

.form-title{
    font-size: 2rem;
    font-family: "Google Sans";
    font-weight: normal;
    margin: 10px;
    width: -webkit-fill-available;
    width: -moz-available;
}

.form-description{
    font-size: 1rem;
    font-family: "Roboto Condensed";
    margin: 10px;
    width: -webkit-fill-available;
    width: -moz-available;
}

.form-title-box{
    border-bottom: 1px solid #ddd;
}

.modal{
    display: none;
    position: fixed;
    z-index: 6;
    padding: calc(10vh - 20px) 0;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    overflow: auto;
    background-color: rgb(0, 0, 0);
    background-color: rgba(0, 0, 0, 0.4);
}

.modal-content{
    background-color: #fefefe;
    margin: auto;
    padding: 20px;
    border: 1px solid #888;
    width: 80%;
    max-height: 80%;
    overflow: auto;
    max-width: 600px;
    border-radius: 10px;
}

.modal-close-btn{
    color: #aaa;
    float: right;
    font-size: 28px;
    font-weight: bold;
}

.modal-close-btn:hover, .modal-close-btn:focus{
    color: #000;
    text-decoration: none;
    cursor: pointer;
}

.modal-title{
    font-family: "Google Sans";
    font-size: 1.2rem;
    border-bottom: 1px solid rgb(233, 232, 232);
    margin-bottom: 0;
}

.modal-subtitle{
    font-family: "Roboto Condensed";
    font-size: 1rem;
    font-weight: normal;
}

.setting-form-label{
    font-family: "Roboto Condensed";
}

.modal-division{
    margin: 30px 0;
}
.confirmation-msg-input{
    width: -webkit-fill-available;
    width: -moz-available;
    border-bottom: 1px solid #202124;
    min-height: 20px !important;
}

.setting-options{
    position: relative;
}
.setting-option-cancel{
    margin: 20px 10px;
    cursor: pointer;
    color: #84878b;

}

.btn-save-setting{
    background-color: #673ab7;
    color: #ddd;
    font-size: 1rem;
    font-family: "Google Sans";
}

.setting-preview-form, .setting-preview-form a{
    cursor: pointer;
    color: #bbb;
    font-family: "Google Sans";
    text-decoration: none;
}

.setting-preview-form:hover{
    opacity: .5;
}

.danger-zone{
    font-weight: bold;
    font-family: "Google Sans";
    font-size: 1.4rem;
}

.delete-form-title{
    margin: 0;
    font-family: "Roboto Condensed";
}

.delete-form-description{
    margin: 0;
    font-family: "Poppins";
}

.delete-form-btn{
    font-size: 1rem;
    font-family: "Poppins";
    padding: 3px !important;
    background-color: #E71C23;
    color: #fff;
}

.question-options{
    background-color: #fff;
    margin: 20px 0;
    position: fixed;
    bottom: 10%;
    right: 0;
    border: 1px solid #84878b;
}

.form-option-icon{
    width: 2rem;
    margin: 5px;
    cursor: pointer;
    display: block;
}

.collect-email{
    margin: 10px;
}

.question-title{
    font-family: "Google Sans";
    font-size: 1.3rem;
    font-weight: normal;
}

.require-star{
    color: #E71C23;
}

.require-email-edit{
    padding: 5px;
    border: none;
    border-bottom: 1px solid #84878b;
    width: 50%;
    cursor: not-allowed;
}

.collect-email-desc{
    color: #70757a;
    margin: 10px 0;
}

.open-setting{
    color: #1a73e8;
    cursor: pointer;
}

.question-title{
    font-family: "Google Sans";
    font-size: 1.5rem;
    width: 65%;
}

.question-type-select{
    width: calc(35% - 8px);
    padding: 5px 35px 5px 5px;
    font-size: 1.2rem;
    border: 1px solid #ccc;
    height: 34px;
}

.question-type-select::-ms-expand{
    display: none;
}

.choices{
    margin: 10px 0;
}

.choice{
    margin: 5px 0;
    font-family: "Google Sans";
}

.add-option{
    cursor: pointer;
    color: #70757a;
}

.edit-choice{
    display: inline;
    width: 80%;
    border: none;
    overflow-y: hidden;
    font-family: "Google Sans";
}

.remove-option{
    display: inline;
    font-size: 1.3rem;
    cursor: pointer;
    margin-left: 10px;
}

.choice-option{
    padding: 10px;
    display: block;
    border-top: 1px solid #ccc;
}

.required{
    font-family: "Roboto Condensed";
}

.answers{
    margin: 5px;
    font-family: "Google Sans";
}

.short-answer{
    width: 50%;
    border: none;
    padding: 5px;
    border-bottom: 1px solid #70757a;
}

.long-answer{
    width: -webkit-fill-available;
    width: -moz-available;
    border: none;
    padding: 5px;
    border-bottom: 1px solid #70757a;
}

.question-option-icon{
    width: 1.5rem;
    cursor: pointer;
}
.form-navigation{
    background-color: #fff;
    width: 400px;
    margin: auto;
}

.navigation{
    text-align: center;
    cursor: pointer;
}

.form-navigation .active{
    color:rgb(0, 132, 223);
    font-weight: bold;
    font-family: "Google Sans";
    font-size: 0.8rem;
}

.question-score{
    max-width: calc(25% - 8px);
    display: inline-block;
    font-family: "Google Sans";
    margin: 1rem;
}

.input-score{
    width: 30px;
    border: none;
    border-bottom: 1px solid rgb(0, 132, 223);
}
input[type=number]::-webkit-inner-spin-button, 
input[type=number]::-webkit-outer-spin-button { 
  -webkit-appearance: none;
}

.question-title-score{
    font-family: "Google Sans";
    display: inline-block;
    width: 75%;
    font-size: 1.5rem;
    font-weight: normal;
    margin: 1rem;
}

.answer-key, .feedback{
    margin: 5px 10px;
}
.answer-key-title, .feedback-title{
    margin: 0;
    font-family: "Roboto Condensed";
    display: inline-block;
}

.multiple-choice{
    width: 100%;
    margin: 5px;
}

.btn-submit{
    background-color: #1a73e8;
    color: #fff;
    border: 1px solid #fff;
    cursor: pointer;
}

.required-info{
    color: #E71C23;
    margin: 10px;
}

.edit-form-link{
    width: 4rem;
    height: 4rem;
    position: fixed;
    bottom: 50px;
    right: 0%;
    border-radius: 50%;
    border: 1px solid #5f6368;
}

.response-title{
    font-family: "Google Sans";
    font-size: 1.5rem;
    font-weight: normal;
}

.score-title{
    font-family: "Google Sans";
    margin: 10px;
    font-size: 1.2rem;
    font-weight: normal;
}

.question-title{
    font-family: "Google Sans";
    font-size: 1.5rem;
}

.view-score-btn{
    position: relative;
    background-color: #673ab7;
    color: #ddd;
    font-family: "Google Sans";
    border: 1px solid #ddd;
    padding: 10px 20px;
    margin: 5px 15px;
}

.feedback{
    margin: 10px 5px;
}

.feedback-title{
    font-family: "Poppins";
    font-size: 1.1rem;
    font-weight: normal;
}

.edit-response-link{
    margin-left: 15px;
}

.form-template-label{
    font-family: "Google Sans";
    margin: 10px;
    display: block;
}

.form-animate {
    position: relative;
    display: block;
    overflow: hidden;
}
  
.input-animate {
    width: -webkit-fill-available;
    width: -moz-available;
    border: none;
    display: inline-block;
    outline: none;
    padding: 10px;
    font-size: 20px;
    background-color: transparent;
    border-bottom: 1px solid #7c7c7c;
}
  
.input-onFocus {
    transition: all 0.5s;
    display: inline-block;
    bottom: 0;
    left: -100%;
    position: absolute;
    width: 100%;
    height: 2px;
    background: #1a73e8;
}
  
.form-animate, .input-animate {
    color: inherit;
}
  
.form-animate .input-animate:focus + .input-onFocus {
    left: 0;
}

.response-summary{
    margin: .5rem 1rem;
}

.response-summary-title{
    font-family: "Google Sans";
    font-size: 1rem;
    font-weight: normal;
}

blockquote{
    font-size: 1.4em;
    font-family:Open Sans;
    font-style:italic;
    color: #555555;
    padding: 10px;
    border-left:8px solid #78C0A8 ;
    position: relative;
    background:#EDEDED;
}
  
blockquote span{
    display:block;
    color:#333333;
    font-style: normal;
    font-weight: bold;
    margin-top:1em;
}

.pie-chart{
    width: 70% !important;
    height: 70% !important;
    margin: auto;
}
@media only screen and (max-width: 768px){
    .nav-form-title{
        width: 100px;
    }

    .form-list-link, .form-box{
        width: -webkit-fill-available;
        width: -moz-available;
    }
    .modal{
        padding: 0;
    }

    .modal-content{
        max-width: none;
        max-height: none;
        width: -webkit-fill-available;
        width: -moz-available;
        height: calc(100% - 40px);
        border-radius: 0%;
    }
    .question-title, .question-title-score{
        width: 100%;
    }
    .question-type-select{
        width: 100%;
        display: block;
    }

    .big-screen{
        display: none;
    }
    .navigation{
        width: calc((100% - 60px)/3) !important;
    }
    .question-score{
        max-width: 100%;
        width: 100%;
    }
    .input-score{
        width: 50px;
    }
}

@media only screen and (min-width: 768px){
    .small-screen{
        display: none;
    }
}

================================================
FILE: index/static/index/viewform.js
================================================
document.addEventListener("DOMContentLoaded", () => {
    document.body.style.backgroundColor =  document.querySelector("#bg-color").innerHTML;
    document.body.style.color =  document.querySelector("#text-color").innerHTML;
    document.querySelectorAll(".txtClr").forEach(element => {
        element.style.color = document.querySelector("#text-color").innerHTML;
    })
    document.querySelectorAll(".textarea-adjust").forEach(tx => {
        tx.style.height = "auto";
        tx.style.height = (10 + tx.scrollHeight)+"px";
        tx.addEventListener('input', e => {
            tx.style.height = "auto";
            tx.style.height = (10 + tx.scrollHeight)+"px";
        })
    })
    document.querySelectorAll('input[type="checkbox"]').forEach(element => {
        document.getElementsByName(element.name).forEach(checkbox => {
            checkbox.addEventListener("input", function(){
                let totalChecked = 0
                document.getElementsByName(element.name).forEach(checkbox => {
                    if(checkbox.checked) totalChecked++;
                })
                if(totalChecked > 0){
                    document.getElementsByName(element.name).forEach(checkbox => {
                        checkbox.removeAttribute("required")
                    })
                }else{
                    document.getElementsByName(element.name).forEach(checkbox => {
                        checkbox.setAttribute("required", '')
                    })
                }
            })
        })
    })
})

================================================
FILE: index/templates/error/403.html
================================================
{% extends 'index/layout.html' %}
{% block body %}
<h1 class="text-danger error-page">Error 403 Forbidden.</h1>
{% endblock %}

================================================
FILE: index/templates/error/404.html
================================================
{% extends 'index/layout.html' %}
{% block body %}
<h1 class="text-danger error-page">Error 404 not found</h1>
{% endblock %}

================================================
FILE: index/templates/index/edit_response.html
================================================
{% extends 'index/layout.html' %}
{% load static %}
{% load get_response %}
{% load to_int %}
{% load is_response %}
{% block title %}{{form.title}} ~ Google Forms CLONE{% endblock %}
{% block script %}
<script src="{% static 'index/viewform.js' %}" defer></script>
{% endblock %}
{% block body %}
<div class="container-fluid">
    <form class="container" method="POST" action="{% url 'edit_response' form.code response.response_code %}" autocomplete="off">
        <span id="bg-color" style="display: none;">{{form.background_color}}</span>
        <span id="text-color" style="display: none;">{{form.text_color}}</span>
        {% csrf_token %}
        <div class="margin-top-bottom box question-box">
            <div class="form-title-box">
                <h1 class="form-title txtClr">{{form.title}}</h1>
                <p class="required-info">* Required</p>
            </div>
            <div class="form-description txtClr">{{form.description|linebreaksbr}}</div>
        </div>
        {% if form.collect_email %}
        <div class="margin-top-bottom box question-box">
            <h1 class="question-title txtClr">Email address: <span class="require-star">*</span></h1>
            <input type="email" name="email-address" class="short-answer" placeholder="Your email address" required value="{{response.responder_email}}">
        </div>
        {% endif %}
        {% for question in form.questions.all %}
        <div class="margin-top-bottom box question-box">
            {% if form.is_quiz %}
            <h1 class="question-title txtClr">{{question.question}} {% if question.required %}<span class="require-star">*</span>{% endif %}</h1>
            {% else %}
            <h1 class="question-title txtClr" oncopy = "return false">{{question.question}} {% if question.required %}<span class="require-star">*</span>{% endif %}</h1>
            {% endif %}
            {% if question.question_type == "short" %}
                <input type="text" name="{{question.id}}" class="short-answer" placeholder = "Your answer" {% if question.required %} required {% endif %}
                value="{{response|get_response:question.pk}}">
            {% elif question.question_type == "paragraph" %}
                <textarea name="{{question.id}}" placeholder="Your answer" class="long-answer textarea-adjust" 
                {% if question.required %} required {% endif %}>{{response|get_response:question.pk}}</textarea>
            {% elif question.question_type == "multiple choice" %}
                {% for choice in question.choices.all %}
                <div class="multiple-choice">
                    {% if response|get_response:question.pk|to_int == choice.pk|to_int %}
                    <input type="radio" name="{{question.id}}" id="{{choice.id}}" {% if question.required %} required {% endif %} value="{{choice.id}}" checked>
                    {% else %}
                    <input type="radio" name="{{question.id}}" id="{{choice.id}}" {% if question.required %} required {% endif %} value="{{choice.id}}">
                    {% endif %}
                    <label for="{{choice.id}}" class="txtClr">{{choice.choice}}</label>
                </div>
                {% endfor %}
            {% elif question.question_type == "checkbox" %}
            {% for choice in question.choices.all %}
                <div class="multiple-choice">
                    {% if response|get_responses:question.pk|is_response:choice.pk %}
                    <input type="checkbox" name="{{question.id}}" id="{{choice.id}}" {% if question.required %} required {% endif %} value="{{choice.id}}" checked>
                    {% else %}
                    <input type="checkbox" name="{{question.id}}" id="{{choice.id}}" {% if question.required %} required {% endif %} value="{{choice.id}}">
                    {% endif %}
                    <label for="{{choice.id}}" class="txtClr">{{choice.choice}}</label>
                </div>
                {% endfor %}
            {% endif %}
        </div>
        {% endfor %}
        <div class="margin-top-bottom">
            <input type="submit" value="Submit" class="btn btn-submit">
        </div>
    </form>
    {% if user == form.creator %}
        <a href="{% url 'edit_form' form.code %}">
            <img src="{% static 'Icon/question.png' %}" alt="Edit Question" title="Edit this form" class="edit-form-link">
        </a>
    {% endif %}
</div>
{% endblock %}

================================================
FILE: index/templates/index/form.html
================================================
{% extends 'index/layout.html' %}
{% block title %}
{{form.title}} ~ Google Forms CLONE
{% endblock %}
{% load static %}
{% block script %}
<script src="{% static 'index/form.js' %}"></script>
<script src="{% static 'lib/cookie.min.js' %}"></script>
{% endblock %}
{% block body %}
<div class = "container-fluid">
    <div class="form-topnav">
        <a href = "/">
            <img src = "{% static 'Icon/icon.png' %}" alt = "Google Forms Icon(CLONE)" class="navbar-icon form-icon" title = "Forms" />
        </a>
        <input class="nav-text nav-form-title edit-on-click input-form-title" value  = "{{form.title}}" type="text">
        <div class="float-right">
            <img src="{% static 'Icon/theme.png' %}" alt="Theme icon" id="customize-theme-btn" title = "Customize theme" class="nav-form-menu-icon" />
            <a href="{% url 'view_form' form.code %}">
            <img src="{% static 'Icon/eye.png' %}" alt="Preview icon" title = "Preview" class="nav-form-menu-icon big-screen" />
            </a>
            <img src="{% static 'Icon/send.png' %}" alt ="Send icon" title = "Send" class="nav-form-menu-icon small-screen" id="send-form-btn" />
            <img src="{% static 'Icon/setting.png' %}" alt="Setting icon" title = "Setting" class="nav-form-menu-icon open-setting" />
            <button class = "btn send-form-btn big-screen" title = "Send" id="send-form-btn">Send</button>
        </div>
    </div>
    <div class="form-topnav">
        <div class="form-navigation center">
            {% if form.is_quiz %}
            <span class="col-4 navigation active">Questions</span>
            <span class="col-4 navigation score"><a href = "{% url 'score' form.code %}" class="link">Scores</a></span>
            <span class="col-4 navigation"><a href = "{% url 'responses' form.code %}" class="link">Responses</a></span>
            {% else %}
            <span class="col-6 navigation active">Questions</span>
            <span class="col-6 navigation"><a href = "{% url 'responses' form.code %}" class="link">Responses</a></span>
            {% endif %}
        </div>
    </div>
    <div class="container">
        <span id="bg-color" style="display: none;">{{form.background_color}}</span>
        <span id="text-color" style="display: none;">{{form.text_color}}</span>
        <div class="margin-top-bottom box question-box" id="form-head">
            <div class="form-title-box">
                <input type="text" class="form-title edit-on-click input-form-title txt-clr" value="{{form.title}}">
            </div>
            <textarea class="form-description edit-on-click textarea-adjust txt-clr" rows="1" placeholder="Form description" spellCheck = "false"
            id="input-form-description">{{form.description}}</textarea>
            {% if form.collect_email %}
            <div class="collect-email txt-clr">
                <h3 class="question-title">Email address <span class="require-star">*</span></h3>
                <input type="text" autocomplete="off" aria-label="Valid email address" disabled dir = "auto" class="require-email-edit txtColor"
                placeholder = "Valid email address" />
                <p class="collect-email-desc">This form is collecting email addresses. <span class="open-setting">Change settings</span></p>
            </div>
            {% endif %}
        </div>
        {% for question in form.questions.all %}
        <div class="margin-top-bottom box question-box question" data-id="{{question.id}}">
            <input type="text" data-id="{{question.id}}" class="question-title edit-on-click input-question" value="{{question.question}}">
            <select class="question-type-select input-question-type" data-id="{{question.id}}" data-origin_type = "{{question.question_type}}">
                <option value="short" {% if question.question_type == "short" %}selected{% endif %}>Short answer</option>
                <option value="paragraph" {% if question.question_type == "paragraph" %}selected{% endif %}>Paragraph</option>
                <option value="multiple choice" {% if question.question_type == "multiple choice" %}selected{% endif %}>Multiple choice</option>
                <option value="checkbox" {% if question.question_type == "checkbox" %}selected{% endif %}>Checkbox</option>
            </select>
            {% if question.question_type == "multiple choice" %}
            <div class="choices" data-id="{{question.id}}">
                {% for choice in question.choices.all %}
                    <div class="choice">
                        <input type="radio" id="{{choice.id}}" disabled>
                        <label for="{{choice.id}}">
                            <input type="text" value="{{choice.choice}}" class="edit-choice" data-id="{{choice.id}}">
                        </label>
                        <span class="remove-option" title = "Remove" data-id="{{choice.id}}">&times;</span>
                    </div>
                {% endfor %}
                <div class="choice">
                    <input type = "radio" id = "add-choice" disabled />
                    <label for = "add-choice" class="add-option" data-question="{{question.id}}" data-type = "{{question.question_type}}">Add option</label>
                </div>
            </div>
            {% elif question.question_type == "checkbox" %}
            <div class="choices" data-id="{{question.id}}">
                {% for choice in question.choices.all %}
                    <div class="choice">
                        <input type="checkbox" id="{{choice.id}}" disabled>
                        <label for="{{choice.id}}">
                            <input type="text" data-id="{{choice.id}}" class="edit-choice" value="{{choice.choice}}">
                        </label>
                        <span class="remove-option" title="Remove" data-id="{{choice.id}}">&times;</span>
                    </div>
                {% endfor %}
                <div class="choice">
                    <input type = "checkbox" id = "add-choice" disabled />
                    <label for = "add-choice" class="add-option" id="add-option" data-question="{{question.id}}" data-type = "{{question.question_type}}">Add option</label>
                </div>
            </div>
            {% elif question.question_type == "short" %}
            <div class="answers" data-id="{{question.id}}">
                <input type ="text" class="short-answer" disabled placeholder="Short answer text" />
            </div>
            {% elif question.question_type == "paragraph" %}
            <div class="answers" data-id="{{question.id}}">
                <textarea class="long-answer" disabled placeholder="Long answer text" ></textarea>
            </div>
            {% endif %}
            <div class="choice-option">
                <input type="checkbox" class="required-checkbox" id="required-{{question.id}}" data-id="{{question.id}}" {% if question.required %}checked{% endif %}>
                <label for="required-{{question.id}}" class="required">Required</label>
                <div class="float-right">
                    <img src="{% static 'Icon/dustbin.png' %}" alt="Delete question icon" class="question-option-icon delete-question" title="Delete question"
                    data-id="{{question.id}}">
                </div>
            </div>
        </div>
        {% endfor %}
    </div>
    <div class="question-options">
        <img src = "{% static 'Icon/add.png' %}" class="form-option-icon" title = "Add question" alt = "Add question icon" id="add-question" />
        <a href="{% url 'view_form' form.code %}">
            <img src = "{% static 'Icon/eye.png' %}" class = "form-option-icon" title = "Preview" alt = "Preview icon" />
        </a>
        {% if form.is_quiz %}
        <a href = "{% url 'score' form.code %}" id="add-score">
            <img src = "{% static 'Icon/score.png' %}" class = "form-option-icon" title = "Add score" alt = "Score icon" />
        </a>
        {% endif %}
    </div>
    <div class="modal" id="customize-theme">
        <div class="modal-content">
            <span class="modal-close-btn" id="close-customize-theme">&times;</span>
            <h1 class="modal-title">Theme options</h1>
            <h3 class="modal-subtitle">Background Color:</h3>
            <input type="color"  value = "{{form.background_color}}" list="bgColors" class="form-control" id="input-bg-color" />
            <datalist id="bgColors">
                <option value="#03a9f4"></option>
                <option value="#00bcd4"></option>
                <option value="#7ff0e7"></option>
                <option value = "#e1d8f1"></option>
                <option value = "#d1c4e9"></option>
                <option value = "#f6f6f6"></option>
                <option value="#f1f3f4"></option>
                <option value="#9aa0a2"></option>
                <option value="#d8ef89"></option>
            </datalist>
            <h3 class="modal-subtitle">Text Color:</h3>
            <input type="color"  value = {{form.text_color}} list="textColors" class="form-control" id="input-text-color" />
            <datalist id="textColors">
                <option value="#db4437"></option>
                <option value="#673ab7"></option>
                <option value="#3f51b5"></option>
                <option value="#4285f4"></option>
                <option value="#03a9f4"></option>
                <option value="#00bcd4"></option>
                <option value="#8a8a8a"></option>
                <option value="#4c3d45"></option>
                <option value="#272124"></option>
            </datalist>
        </div>
    </div>
    <div class="modal" id="setting">
        <div class="modal-content txt-clr">
            <form id="setting-form">
                <span class="modal-close-btn" id="close-setting">&times;</span>
                <h1 class = "modal-title">Setting</h1>
                <h4 class="setting-preview-form small-screen"><a href="{% url 'view_form' form.code %}">Preview form here</a></h4>
                <div class="modal-division">
                    <div class="form-group">
                        <h3 class="modal-subtitle">General</h3>
                        <input type="checkbox" id="collect_email"{% if form.collect_email %} checked {% endif %}>
                        <label for="collect_email" class="setting-form-label">Collect email address</label>
                    </div>
                    <div class="form-group">
                        <input type="checkbox" id="is_quiz" {% if form.is_quiz %} checked {% endif %}>
                        <label for="is_quiz" class="setting-form-label">Make this as a quiz</label>
                    </div>
                    <div class="form-group">
                        <input type="checkbox" id="authenticated_responder" {% if form.authenticated_responder %} checked {% endif %}>
                        <label for="authenticated_responder" class="setting-form-label">Respondent account must be authenticated. (Signed in required)</label>
                    </div>
                </div>
                <div class="modal-division">
                    <div class="form-group">
                        <h3 class="modal-subtitle">Confirmation message:</h3>
                        <textarea rows="1" class="confirmation-msg-input edit-on-click textarea-adjust" spellcheck="false"
                         id="comfirmation_message">{{form.confirmation_message}}</textarea>
                    </div>
                </div>
                <div class="modal-division">
                    <div class="form-group">
                        <h3 class="modal-subtitle">Respondents can:</h3>
                        <input type="checkbox" id="edit_after_submit" {% if form.edit_after_submit %}checked{% endif %}>
                        <label for="edit_after_submit" class="setting-form-label">Edit after submit</label>
                    </div>
                    <div class="form-group">
                        <input type="checkbox" id="allow_view_score" {% if form.allow_view_score %}checked{% endif %}>
                        <label for="allow_view_score" class="setting-form-label">View score</label>
                    </div>
                    <div class="form-group">
                        <input type="submit" value="Save" class="form-control btn btn-save-setting">
                    </div>
                </div>
            </form>
            <form id="delete-form" class="modal-division">
                <fieldset class="form-group">
                    <legend class="modal-subtitle text-danger danger-zone">Danger Zone</legend>
                    <h3 class="delete-form-title">Delete this form</h3>
                    <p class="delete-form-description">Once you delete a form, there is no going back. Please be certain.</p>
                    <input type="submit" value="Delete" class="form-control delete-form-btn">
                </fieldset>
            </form>
        </div>
    </div>
    <div class="modal" id="send-form">
        <div class="modal-content">
            <span class="modal-close-btn" id="close-send-form">&times;</span>
            <h1 class = "modal-title">Send form</h1>
            <div class="modal-division">
                <h4 class="modal-subtitle">Link:</h4>
                <input type="url" class="form-control" value="http://{{request.get_host}}/form/{{form.code}}/viewform" copy-btn id="copy-url">
            </div>
            <button class="btn btn-submit" copy-btn>Copy</button>
        </div>
    </div>
</div>
{% endblock %}

================================================
FILE: index/templates/index/form_response.html
================================================
{% extends 'index/layout.html' %}
{% load static %}
{% block script %}
<script src="{% static 'index/viewform.js' %}" defer></script>
{% endblock %}
{% block body %}
<div class="container">
    <span id="bg-color" style="display: none;">{{form.background_color}}</span>
    <span id="text-color" style="display: none;">{{form.text_color}}</span>
    <div class="margin-top-bottom box box-shadow bg-white">
        <h1 class="form-title txtClr">{{form.title}}</h1>
        <p class="text-label margin-left-right" style="margin-left: 10px;">{{form.confirmation_message}}</p>
        {% if form.edit_after_submit %}
        <a href="{% url 'edit_response' form.code code %}" class="edit-response-link">Edit response</a>
        {% endif %}
        {% if form.is_quiz and form.allow_view_score %}
        <div class="modal-division">
            <a href="{% url 'response' form.code code %}" class="btn view-score-btn">View Score</a>
        </div>
        {% endif %}
    </div>
</div>
{% endblock %}

================================================
FILE: index/templates/index/index.html
================================================
{% extends 'index/layout.html' %}
{% load static %}
{% block script %}
<script src = "{% static 'index/index.js' %}" defer></script>
<script src="{% static 'lib/cookie.min.js' %}" defer></script>
{% endblock %}
{% load static %}
{% block body %}
<div class="container-fluid">
    <div class="topnav nav-effect">
        <div class="nav-padding">
            <span class="nav-ham" id="nav-ham">&#9776;</span>
            <img src = "{% static 'Icon/icon.png' %}" alt = "Google Forms Icon(CLONE)" class="navbar-icon form-icon" title = "Forms">
            <span class="nav-text" title = "Forms"><a href = "{% url 'index' %}" class="nav-link">Forms CLONE</a></span>
            <a href="{% url 'logout' %}">
                <img src = "{% static 'Icon/Logout.jpg' %}" alt = "Logout Icon" class="navbar-icon float-right logout-icon" title = "Logout">
            </a>
        </div>
    </div>
    <div class="sidebar" id = "sidebar">
        <span class="close-sidebar" id="close-sidebar">&times;</span>
        <div class="sidebar-content">
            <h4 class="sidebar-title">
                <a href = "{% url 'index' %}" class="sidebar-title-link">
                    <span>Google Forms CLONE</span>
                </a>
            </h4>
            <p class="text-label">Found bug? Submit an issue <a href="https://github.com/kimlimjustin/google-form-clone/issues" class="link">here</a></p>
            <p class="text-label">License: <a href="https://github.com/kimlimjustin/google-form-clone/blob/master/LICENSE" class="link">MIT</a></p>
            <p class="text-label">Source code: <a href="https://github.com/kimlimjustin/google-form-clone">
                <img src = "{% static 'Icon/github.png' %}" class="github-icon" alt="GitHub"></a></p>
            <p class="text-label">Support creator by <a href="https://github.com/kimlimjustin/google-form-clone" class="link">give a star on GitHub</a></p>
        </div>
    </div>
    <div class="create-form">
        <div class="container">
            <p class="forms-label">Start a new form</p>
            <div class="form-template-box">
                <img src = "{% static 'Icon/blank-form.png' %}" alt = "Blank form" title = "Blank form" id="create-blank-form">
                <span class="form-template-label">Blank Form</span>
            </div>
            <div class="form-template-box big-screen">
                <img src = "{% static 'Template/contact_information.png' %}" alt = "Contact Information" title = "Contact Information" id="create-contact-form">
                <span class="form-template-label">Contact Information</span>
            </div>
            <div class="form-template-box big-screen">
                <img src = "{% static 'Template/customer_feedback.png' %}" alt = "Customer Feedback" title = "Customer Feedback" id="create-customer-feedback">
                <span class="form-template-label">Customer Feedback</span>
            </div>
            <div class="form-template-box big-screen">
                <img src = "{% static 'Template/customer_feedback.png' %}" alt = "Event Registration" title = "Event Registration" id="create-event-registration">
                <span class="form-template-label">Event Registration</span>
            </div>
        </div>
    </div>
    <div class="container">
        <div class="form-list">
            <p class="forms-label">Your forms:</p>
            {% for i in forms %}
            <a href = "{% url 'edit_form' i.code %}" class="form-list-link">
                <div class="form-box">
                    <div class="form-list-title"><h5 class="form-list-title-text">{{i.title}}</h5></div>
                    {% if i.createdAt == i.updatedAt %}
                    <p class="form-list-timestamp">{{i.createdAt}}</p>
                    {% else %}
                    <p class="form-list-timestamp">{{i.updatedAt}}</p>
                    {% endif %}
                </div>
            </a>
            {% endfor %}
        </div>
    </div>
</div>
{% endblock %}

================================================
FILE: index/templates/index/layout.html
================================================
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{% block title %}Google Forms CLONE{% endblock %}</title>
    <link rel="stylesheet" href="{% static 'index/HurlUI.css' %}">
    <link rel="stylesheet" href="{% static 'index/style.css' %}">
    {% block script %}
    {% endblock %}
</head>
<body>
    {% block body %}
    {% endblock %}
</body>
</html>

================================================
FILE: index/templates/index/login.html
================================================
{% extends 'index/layout.html' %}
{% block body %}
<div class="container">
    <form class="box box-shadow margin-top-bottom" method="POST" action = "{% url 'login' %}">
        <div class="form-group">
            <h1 class="box-title">Login user</h1>
            <p class="form-error">{{message}}</p>
            {% csrf_token %}
        </div>
        <div class="form-group form-animate">
            <p class="form-label">Username</p>
            <input type="text" class="input-animate" required name="username">
            <span class="input-onFocus"></span>
        </div>
        <div class="form-group form-animate">
            <p class="form-label">Password:</p>
            <input type="password" name="password" class="input-animate" required>
            <span class="input-onFocus"></span>
        </div>
        <div class="form-group">
            <p class="form-label">Don't have account yet? <a class="link" href = "{% url 'register' %}">Register</a></p>
            <input type="submit" value="Login" class="btn btn-dark form-control">
        </div>
    </form>
</div>
{% endblock %}

================================================
FILE: index/templates/index/register.html
================================================
{% extends 'index/layout.html' %}
{% block body %}
<div class="container">
    <form action="{% url 'register' %}" method="post" class="box box-shadow margin-top-bottom">
        <div class="form-group">
            <h1 class="box-title">Register user</h1>
            <p class="form-error">{{message}}</p>
            {% csrf_token %}
        </div>
        <div class="form-group form-animate">
            <p class="form-label">Username:</p>
            <input type="text" class="form-control input-animate" name="username" required>
            <span class="input-onFocus"></span>
        </div>
        <div class="form-group form-animate">
            <p class="form-label">Email:</p>
            <input type="email" name="email" class="form-control input-animate" required>
            <span class="input-onFocus"></span>
        </div>
        <div class="form-group form-animate">
            <p class="form-label">Password:</p>
            <input type="password" name="password" class="form-control input-animate" required>
            <span class="input-onFocus"></span>
        </div>
        <div class="form-group form-animate">
            <p class="form-label">Password Confirmation:</p>
            <input type="password" name="confirmation" class="form-control input-animate" required>
            <span class="input-onFocus"></span>
        </div>
        <div class="form-group">
            <p class="form-label">Already have account? <a class="link" href = "{% url 'login' %}">Login</a></p>
            <input type="submit" value="Register" class="btn btn-dark form-control">
        </div>
    </form>
</div>
{% endblock %}

================================================
FILE: index/templates/index/response.html
================================================
{% extends 'index/layout.html' %}
{% load static %}
{% load get_response %}
{% load to_int %}
{% load is_response %}
{% load score %}
{% block script %}
<script src="{% static 'index/response.js' %}"></script>
{% endblock %}
{% block body %}
<div class="container-fluid">
    <div class="container">
        <span id="bg-color" style="display: none;">{{form.background_color}}</span>
        <span id="text-color" style="display: none;">{{form.text_color}}</span>
        <div class="margin-top-bottom box question-box">
            <div class="form-title-box">
                <h1 class="form-title txtClr">{{form.title}}</h1>
                {% if form.is_quiz %}
                <h4 class="score-title">Score: {{score}} / {{total_score}}</h4>
                {% endif %}
                <p class="required-info">* Required</p>
            </div>
            <div class="form-description txtClr">{{form.description|linebreaksbr}}</div>
        </div>
        {% if form.collect_email %}
        <div class="margin-top-bottom box question-box">
            <h1 class="question-title txtClr">Email address: <span class="require-star">*</span></h1>
            <p class="short-answer">{{response.responder_email}}</p>
        </div>
        {% endif %}
        {% for question in form.questions.all %}
        <div class="margin-top-bottom box question-box">
            <h1 class="response-title txtClr">{{question.question}} {% if question.required %}<span class="require-star">*</span>{% endif %}
            {% if form.is_quiz %}<span class="float-right">{{response|score:question.pk}} / {{question.score}}</span>{% endif %}</h1>
            {% if question.question_type == "short" %}
                <p class="short-answer">{{response|get_response:question.pk}}</p>
            {% elif question.question_type == "paragraph" %}
                <p class="long-answer">{{response|get_response:question.pk|linebreaksbr}}</p>
            {% elif question.question_type == "multiple choice" %}
                {% for choice in question.choices.all %}
                <div class="multiple-choice">
                    {% if response|get_response:question.pk|to_int == choice.pk|to_int %}
                        <input type="radio" name="{{question.id}}" id="{{choice.id}}" checked>
                    {% else %}
                        <input type="radio" name="{{question.id}}" id="{{choice.id}}" disabled>
                    {% endif %}
                    <label for="{{choice.id}}" class="txtClr">{{choice.choice}}</label>
                </div>
                {% endfor %}
            {% elif question.question_type == "checkbox" %}
                {% for choice in question.choices.all %}
                <div class="multiple-choice">
                    {% if response|get_responses:question.pk|is_response:choice.pk %}
                        <input type="checkbox" name="{{question.id}}" id="{{choice.id}}" value="{{choice.id}}" checked onclick="return false">
                    {% else %}
                        <input type="checkbox" name="{{question.id}}" id="{{choice.id}}" value="{{choice.id}}" disabled>
                    {% endif %}
                    <label for="{{choice.id}}" class="txtClr">{{choice.choice}}</label>
                </div>
                {% endfor %}
            {% endif %}
            {% if user != form.creator and question.feedback != None and question.feedback != "" %}
                <div class="feedback">
                    <h5 class="feedback-title">Feedback:</h5>
                    <p class="text-label long-answer">{{question.feedback|linebreaksbr|urlize}}</p>
                </div>
            {% endif %}
        </div>
        {% endfor %}
    </div>
    {% if user == form.creator %}
        <a href="{% url 'edit_form' form.code %}">
            <img src="{% static 'Icon/question.png' %}" alt="Edit Question" title="Edit this form" class="edit-form-link">
        </a>
    {% endif %}
</div>
{% endblock %}

================================================
FILE: index/templates/index/responses.html
================================================
{% extends 'index/layout.html' %}
{% load static %}
{% load get_property %}
{% load generate_color %}
{% load count %}
{% block title %}{{form.title}}'s response ~ Google Forms CLONE{% endblock %}
{% block script %}
<script src="{% static 'index/responses.js' %}" defer></script>
<script src="{% static 'lib/cookie.min.js' %}"></script>
{% endblock %}
{% block body %}
<div class="container-fluid">
    <div class="form-topnav">
        <a href = "/">
            <img src = "{% static 'Icon/icon.png' %}" alt = "Google Forms Icon(CLONE)" class="navbar-icon form-icon" title = "Forms" />
        </a>
        <span class="nav-text nav-form-title input-form-title">{{form.title}}</span>
        <div class="float-right">
            <img src="{% static 'Icon/theme.png' %}" alt="Theme icon" id="customize-theme-btn" title = "Customize theme" class="nav-form-menu-icon" />
            <a href="{% url 'view_form' form.code %}">
            <img src="{% static 'Icon/eye.png' %}" alt="Preview icon" title = "Preview" class="nav-form-menu-icon big-screen" />
            </a>
            <img src="{% static 'Icon/send.png' %}" alt ="Send icon" title = "Send" class="nav-form-menu-icon small-screen" id="send-form-btn" />
            <img src="{% static 'Icon/setting.png' %}" alt="Setting icon" title = "Setting" class="nav-form-menu-icon open-setting" />
            <button class = "btn send-form-btn big-screen" title = "Send" id="send-form-btn">Send</button>
        </div>
    </div>
    <div class="form-topnav">
        <div class="form-navigation center">
            {% if form.is_quiz %}
            <span class="col-4 navigation"><a href = "{% url 'edit_form' form.code %}" class="link">Questions</a></span>
            <span class="col-4 navigation score"><a href="{% url 'score' form.code %}" class="link">Scores</a></span>
            <span class="col-4 navigation active">Responses</span>
            {% else %}
            <span class="col-6 navigation"><a href = "{% url 'edit_form' form.code %}" class="link">Questions</a></span>
            <span class="col-6 navigation active">Responses</span>
            {% endif %}
        </div>
    </div>
    <div class="container">
        <span id="bg-color" style="display: none;">{{form.background_color}}</span>
        <span id="text-color" style="display: none;">{{form.text_color}}</span>
        <div class="margin-top-bottom box question-box" id="responses">
            {% if responses.count > 0 %}
            <h1 class="response-title">Individual Response:</h1>
            <ul>
                {% for i in responses %}
                    {% if form.collect_email %}
                        <li><a href = "{% url 'response' form.code i.response_code %}" class="link">{{i.responder_email}}'s response</a></li>
                    {% elif form.authenticated_responder %}
                        <li><a href = "{% url 'response' form.code i.response_code %}" class="link">{{i.responder.username}}'s response</a></li>
                    {% else %}
                        <li><a href = "{% url 'response' form.code i.response_code %}" class="link">{{i.responder_ip}}'s response</a></li>
                    {% endif %}
                {% endfor %}
            </ul>
            <button class="btn btn-danger" id="delete-responses">Delete all responses</button>
            <a href="{% url 'export_csv' form.code  %}"><button class="btn btn-success" id="delete-responses">download</button></a>
            {% else %}
            <h1 class="response-title">0 responses</h1>
            {% endif %}
        </div>
        <div class="margin-top-bottom box question-box">
            <h1 class="response-title">Questions Summary:</h1>
            {% for r in responsesSummary %}
            <div class="response-summary">
                <h3 class="response-summary-title">{{r.question.question}}</h3>
                {% if r.answers|count > 0 or filteredResponsesSummary|get_property:r.question.question|count > 0 %}
                    {% if r.question.question_type == 'short' or r.question.question_type == 'paragraph' %}
                        {% for i in r.answers %}
                            <blockquote>{{i.answer}}</blockquote>
                        {% endfor %}
                    {% else %}
                            <canvas id="myChart{{r.question.id}}" class="pie-chart"></canvas>
                            <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.min.js"></script>
                            <script>
                                Chart.defaults.global.defaultFontFamily = "Roboto";
                                Chart.defaults.global.defaultFontSize = 30;
                                var ctx = document.getElementById("myChart{{r.question.id}}");
                                let chartData{{r.question.id}} = {labels: [{% for i in filteredResponsesSummary|get_property:r.question.question %}"{{i}}",{% endfor %}], 
                                datasets: [{
                                    data: [{% for i in filteredResponsesSummary|get_property:r.question.question %}{{filteredResponsesSummary|get_property:r.question.question|get_property:i}},{% endfor %}],
                                    backgroundColor: [{% for _ in filteredResponsesSummary|get_property:r.question.question %}"{{0|generate_color}}",{% endfor %}],
                                }]}
                                new Chart(ctx, {type: 'pie', data: chartData{{r.question.id}}, options: {responsive: true}});
                            </script>
                    {% endif %}
                {% else %}
                <blockquote><i>No responses</i></blockquote>
                {% endif %}
            </div>
            {% endfor %}
        </div>
    <div class="question-options">
        <a href="{% url 'view_form' form.code %}">
            <img src = "{% static 'Icon/eye.png' %}" class = "form-option-icon" title = "Preview" alt = "Preview icon" />
        </a>
        <a href="{% url 'edit_form' form.code %}">
            <img src="{% static 'Icon/question.png' %}" alt="Edit Question" title="Edit this form" class="form-option-icon">
        </a>
        {% if form.is_quiz %}
        <a href = "{% url 'score' form.code %}" id="add-score">
            <img src = "{% static 'Icon/score.png' %}" class = "form-option-icon" title = "Add score" alt = "Score icon" />
        </a>
        {% endif %}
    </div>
    <div class="modal" id="customize-theme">
        <div class="modal-content">
            <span class="modal-close-btn" id="close-customize-theme">&times;</span>
            <h1 class="modal-title">Theme options</h1>
            <h3 class="modal-subtitle">Background Color:</h3>
            <input type="color"  value = "{{form.background_color}}" list="bgColors" class="form-control" id="input-bg-color" />
            <datalist id="bgColors">
                <option value="#03a9f4"></option>
                <option value="#00bcd4"></option>
                <option value="#7ff0e7"></option>
                <option value = "#e1d8f1"></option>
                <option value = "#d1c4e9"></option>
                <option value = "#f6f6f6"></option>
                <option value="#f1f3f4"></option>
                <option value="#9aa0a2"></option>
                <option value="#d8ef89"></option>
            </datalist>
            <h3 class="modal-subtitle">Text Color:</h3>
            <input type="color"  value = {{form.text_color}} list="textColors" class="form-control" id="input-text-color" />
            <datalist id="textColors">
                <option value="#db4437"></option>
                <option value="#673ab7"></option>
                <option value="#3f51b5"></option>
                <option value="#4285f4"></option>
                <option value="#03a9f4"></option>
                <option value="#00bcd4"></option>
                <option value="#8a8a8a"></option>
                <option value="#4c3d45"></option>
                <option value="#272124"></option>
            </datalist>
        </div>
    </div>
    <div class="modal" id="setting">
        <div class="modal-content txt-clr">
            <form id="setting-form">
                <span class="modal-close-btn" id="close-setting">&times;</span>
                <h1 class = "modal-title">Setting</h1>
                <h4 class="setting-preview-form small-screen"><a href="{% url 'view_form' form.code %}">Preview form here</a></h4>
                <div class="modal-division">
                    <div class="form-group">
                        <h3 class="modal-subtitle">General</h3>
                        <input type="checkbox" id="collect_email"{% if form.collect_email %} checked {% endif %}>
                        <label for="collect_email" class="setting-form-label">Collect email address</label>
                    </div>
                    <div class="form-group">
                        <input type="checkbox" id="is_quiz" {% if form.is_quiz %} checked {% endif %}>
                        <label for="is_quiz" class="setting-form-label">Make this as a quiz</label>
                    </div>
                    <div class="form-group">
                        <input type="checkbox" id="authenticated_responder" {% if form.authenticated_responder %} checked {% endif %}>
                        <label for="authenticated_responder" class="setting-form-label">Respondent account must be authenticated. (Signed in required)</label>
                    </div>
                </div>
                <div class="modal-division">
                    <div class="form-group">
                        <h3 class="modal-subtitle">Confirmation message:</h3>
                        <textarea rows="1" class="confirmation-msg-input edit-on-click textarea-adjust" spellcheck="false"
                         id="comfirmation_message">{{form.confirmation_message}}</textarea>
                    </div>
                </div>
                <div class="modal-division">
                    <div class="form-group">
                        <h3 class="modal-subtitle">Respondents can:</h3>
                        <input type="checkbox" id="edit_after_submit" {% if form.edit_after_submit %}checked{% endif %}>
                        <label for="edit_after_submit" class="setting-form-label">Edit after submit</label>
                    </div>
                    <div class="form-group">
                        <input type="checkbox" id="allow_view_score" {% if form.allow_view_score %}checked{% endif %}>
                        <label for="allow_view_score" class="setting-form-label">View score</label>
                    </div>
                    <div class="form-group">
                        <input type="submit" value="Save" class="form-control btn btn-save-setting">
                    </div>
                </div>
            </form>
            <form id="delete-form" class="modal-division">
                <fieldset class="form-group">
                    <legend class="modal-subtitle text-danger danger-zone">Danger Zone</legend>
                    <h3 class="delete-form-title">Delete this form</h3>
                    <p class="delete-form-description">Once you delete a form, there is no going back. Please be certain.</p>
                    <input type="submit" value="Delete" class="form-control delete-form-btn">
                </fieldset>
            </form>
        </div>
    </div>
    <div class="modal" id="send-form">
        <div class="modal-content">
            <span class="modal-close-btn" id="close-send-form">&times;</span>
            <h1 class = "modal-title">Send form</h1>
            <div class="modal-division">
                <h4 class="modal-subtitle">Link:</h4>
                <input type="url" class="form-control" value="http://{{request.get_host}}/form/{{form.code}}/viewform" copy-btn id="copy-url">
            </div>
            <button class="btn btn-submit" copy-btn>Copy</button>
        </div>
    </div>
</div>

{% endblock %}

================================================
FILE: index/templates/index/score.html
================================================
{% extends 'index/layout.html' %}
{% load static %}
{% block title %}{{form.title}} ~ Google Forms CLONE{% endblock %}
{% block script %}
<script src="{% static 'index/score.js' %}" defer></script>
<script src="{% static 'lib/cookie.min.js' %}"></script>
{% endblock %}
{% block body %}
<div class="container-fluid">
    <div class="form-topnav">
        <a href = "/">
            <img src = "{% static 'Icon/icon.png' %}" alt = "Google Forms Icon(CLONE)" class="navbar-icon form-icon" title = "Forms" />
        </a>
        <span class="nav-text nav-form-title input-form-title">{{form.title}}</span>
        <div class="float-right">
            <img src="{% static 'Icon/theme.png' %}" alt="Theme icon" id="customize-theme-btn" title = "Customize theme" class="nav-form-menu-icon" />
            <a href="{% url 'view_form' form.code %}">
            <img src="{% static 'Icon/eye.png' %}" alt="Preview icon" title = "Preview" class="nav-form-menu-icon big-screen" />
            </a>
            <img src="{% static 'Icon/send.png' %}" alt ="Send icon" title = "Send" class="nav-form-menu-icon small-screen" id="send-form-btn" />
            <img src="{% static 'Icon/setting.png' %}" alt="Setting icon" title = "Setting" class="nav-form-menu-icon open-setting" />
            <button class = "btn send-form-btn big-screen" title = "Send" id="send-form-btn">Send</button>
        </div>
    </div>
    <div class="form-topnav">
        <div class="form-navigation center">
            <span class="col-4 navigation"><a href = "{% url 'edit_form' form.code %}" class="link">Questions</a></span>
            <span class="col-4 navigation active">Scores</span>
            <span class="col-4 navigation"><a href = "{% url 'responses' form.code %}" class="link">Responses</a></span>
        </div>
    </div>
    <div class="container">
        <span id="bg-color" style="display: none;">{{form.background_color}}</span>
        <span id="text-color" style="display: none;">{{form.text_color}}</span>
        <div class="margin-top-bottom box question-box" id="form-head">
            <div class="form-title-box">
                <h1 class="form-title edit-on-click txt-clr">{{form.title}}</h1>
            </div>
            <p class="form-description edit-on-click textarea-adjust txt-clr">{{form.description|linebreaksbr}}</p>
            {% if form.collect_email %}
            <div class="collect-email txt-clr">
                <h3 class="question-title">Email address <span class="require-star">*</span></h3>
                <input type="text" autoComplete="off" aria-label="Valid email address" disabled dir = "auto" class="require-email-edit txtColor"
                placeholder = "Valid email address" />
                <p class="collect-email-desc">This form is collecting email addresses. <span class="open-setting">Change settings</span></p>
            </div>
            {% endif %}
        </div>
        {% for question in form.questions.all %}
        <div class="margin-top-bottom box question-box question" data-id="{{question.id}}">
            <h2 class="question-title-score">{{question.question}}</h2>
            <div class="question-score">
                <input type="number" data-id="{{question.id}}" id="score" class="input-score" value="{{question.score}}">
                <label for="score">Points</label>
            </div>
            <div class="answer-key">
                <p class="answer-key-title">Answer key:</p>
                {% if question.question_type == "short" %}
                    <input type="text" class="short-answer" data-id="{{question.id}}" data-question-type = "{{question.question_type}}" answer-key
                    value="{{question.answer_key}}">
                {% elif question.question_type == "paragraph" %}
                    <textarea class="long-answer textarea-adjust" data-question-type = "{{question.question_type}}" answer-key 
                    data-id="{{question.id}}">{{question.answer_key}}
                    </textarea>
                {% elif question.question_type == "multiple choice" %}
                    {% for i in question.choices.all %}
                    <div class="form-group">
                        <input type="radio" name="{{question.id}}-answer" id="choice-{{i.id}}" data-id="{{question.id}}" value="{{i.id}}" answer-key
                        data-question_type = "{{question.question_type}}" {% if i.is_answer %} checked {% endif %}>
                        <label for="choice-{{i.id}}">{{i.choice}}</label>
                    </div>
                    {% endfor %}
                {% elif question.question_type == "checkbox" %}
                    {% for i in question.choices.all %}
                    <div class="form-group">
                        <input type="checkbox" name="{{question.id}}-answer" id="choice-{{i.id}}" data-id="{{question.id}}" value="{{i.id}}"
                        data-question_type = "{{question.question_type}}" answer-key {% if i.is_answer %} checked {% endif %}>
                        <label for="choice-{{i.id}}">{{i.choice}}</label>
                    </div>
                    {% endfor %}
                {% endif %}
            </div>
            <div class="feedback">
                <p class="feedback-title">Feedback:</p>
                {% if question.feedback != None %}
                <textarea class="long-answer textarea-adjust" data-id="{{question.id}}" name="feedback">{{question.feedback}}</textarea>
                {% else %}
                <textarea class="long-answer textarea-adjust" data-id="{{question.id}}" name="feedback"></textarea>
                {% endif %}
            </div>
        </div>
        {% endfor %}
    </div>
    <div class="question-options">
        <a href="{% url 'view_form' form.code %}">
            <img src = "{% static 'Icon/eye.png' %}" class = "form-option-icon" title = "Preview" alt = "Preview icon" />
        </a>
        <a href="{% url 'edit_form' form.code %}">
            <img src = "{% static 'Icon/question.png' %}" class = "form-option-icon" title = "Questions" alt = "Question icon" />
        </a>
    </div>
    <div class="modal" id="customize-theme">
        <div class="modal-content">
            <span class="modal-close-btn" id="close-customize-theme">&times;</span>
            <h1 class="modal-title">Theme options</h1>
            <h3 class="modal-subtitle">Background Color:</h3>
            <input type="color"  value = "{{form.background_color}}" list="bgColors" class="form-control" id="input-bg-color" />
            <datalist id="bgColors">
                <option value="#03a9f4"></option>
                <option value="#00bcd4"></option>
                <option value="#7ff0e7"></option>
                <option value = "#e1d8f1"></option>
                <option value = "#d1c4e9"></option>
                <option value = "#f6f6f6"></option>
                <option value="#f1f3f4"></option>
            </datalist>
            <h3 class="modal-subtitle">Text Color:</h3>
            <input type="color"  value = {{form.text_color}} list="textColors" class="form-control" id="input-text-color" />
            <datalist id="textColors">
                <option value="#db4437"></option>
                <option value="#673ab7"></option>
                <option value="#3f51b5"></option>
                <option value="#4285f4"></option>
                <option value="#03a9f4"></option>
                <option value="#00bcd4"></option>
                <option value="#8a8a8a"></option>
                <option value="#4c3d45"></option>
                <option value="#272124"></option>
                <option value="#9aa0a2"></option>
                <option value="#d8ef89"></option>
            </datalist>
        </div>
    </div>
    <div class="modal" id="setting">
        <div class="modal-content txt-clr">
            <form id="setting-form">
                <span class="modal-close-btn" id="close-setting">&times;</span>
                <h1 class = "modal-title">Setting</h1>
                <h4 class="setting-preview-form small-screen"><a href="{% url 'view_form' form.code %}">Preview form here</a></h4>
                <div class="modal-division">
                    <div class="form-group">
                        <h3 class="modal-subtitle">General</h3>
                        <input type="checkbox" id="collect_email"{% if form.collect_email %} checked {% endif %}>
                        <label for="collect_email" class="setting-form-label">Collect email address</label>
                    </div>
                    <div class="form-group">
                        <input type="checkbox" id="is_quiz" {% if form.is_quiz %} checked {% endif %}>
                        <label for="is_quiz" class="setting-form-label">Make this as a quiz</label>
                    </div>
                    <div class="form-group">
                        <input type="checkbox" id="authenticated_responder" {% if form.authenticated_responder %} checked {% endif %}>
                        <label for="authenticated_responder" class="setting-form-label">Respondent account must be authenticated. (Signed in required)</label>
                    </div>
                </div>
                <div class="modal-division">
                    <div class="form-group">
                        <h3 class="modal-subtitle">Confirmation message:</h3>
                        <textarea rows="1" class="confirmation-msg-input edit-on-click textarea-adjust" spellcheck="false"
                         id="comfirmation_message">{{form.confirmation_message}}</textarea>
                    </div>
                </div>
                <div class="modal-division">
                    <div class="form-group">
                        <h3 class="modal-subtitle">Respondents can:</h3>
                        <input type="checkbox" id="edit_after_submit" {% if form.edit_after_submit %}checked{% endif %}>
                        <label for="edit_after_submit" class="setting-form-label">Edit after submit</label>
                    </div>
                    <div class="form-group">
                        <input type="checkbox" id="allow_view_score" {% if form.allow_view_score %}checked{% endif %}>
                        <label for="allow_view_score" class="setting-form-label">View score</label>
                    </div>
                    <div class="form-group">
                        <input type="submit" value="Save" class="form-control btn btn-save-setting">
                    </div>
                </div>
            </form>
            <form id="delete-form" class="modal-division">
                <fieldset class="form-group">
                    <legend class="modal-subtitle text-danger danger-zone">Danger Zone</legend>
                    <h3 class="delete-form-title">Delete this form</h3>
                    <p class="delete-form-description">Once you delete a form, there is no going back. Please be certain.</p>
                    <input type="submit" value="Delete" class="form-control delete-form-btn">
                </fieldset>
            </form>
        </div>
    </div>
    <div class="modal" id="send-form">
        <div class="modal-content">
            <span class="modal-close-btn" id="close-send-form">&times;</span>
            <h1 class = "modal-title">Send form</h1>
            <div class="modal-division">
                <h4 class="modal-subtitle">Link:</h4>
                <input type="url" class="form-control" value="http://{{request.get_host}}/form/{{form.code}}/viewform" copy-btn id="copy-url">
            </div>
            <button class="btn btn-submit" copy-btn>Copy</button>
        </div>
    </div>
</div>
{% endblock %}

================================================
FILE: index/templates/index/view_form.html
================================================
{% extends 'index/layout.html' %}
{% load static %}
{% block title %}{{form.title}} ~ Google Forms CLONE{% endblock %}
{% block script %}
<script src="{% static 'index/viewform.js' %}" defer></script>
{% endblock %}
{% block body %}
<div class="container-fluid">
    <form class="container" method="POST" action="{% url 'submit_form' form.code %}" autocomplete="off">
        <span id="bg-color" style="display: none;">{{form.background_color}}</span>
        <span id="text-color" style="display: none;">{{form.text_color}}</span>
        {% csrf_token %}
        <div class="margin-top-bottom box question-box">
            <div class="form-title-box">
                <h1 class="form-title txtClr">{{form.title}}</h1>
                <p class="required-info">* Required</p>
            </div>
            <div class="form-description txtClr">{{form.description|linebreaksbr}}</div>
        </div>
        {% if form.collect_email %}
        <div class="margin-top-bottom box question-box">
            <h1 class="question-title txtClr">Email address: <span class="require-star">*</span></h1>
            <input type="email" name="email-address" class="short-answer" placeholder="Your email address" required>
        </div>
        {% endif %}
        {% for question in form.questions.all %}
        <div class="margin-top-bottom box question-box">
            <h1 class="question-title txtClr">{{question.question}} {% if question.required %}<span class="require-star">*</span>{% endif %}</h1>
            {% if question.question_type == "short" %}
                <input type="text" name="{{question.id}}" class="short-answer" placeholder = "Your answer" {% if question.required %} required {% endif %}>
            {% elif question.question_type == "paragraph" %}
                <textarea name="{{question.id}}" placeholder="Your answer" class="long-answer textarea-adjust" {% if question.required %} required {% endif %}></textarea>
            {% elif question.question_type == "multiple choice" %}
                {% for choice in question.choices.all %}
                <div class="multiple-choice">
                    <input type="radio" name="{{question.id}}" id="{{choice.id}}" {% if question.required %} required {% endif %} value="{{choice.id}}">
                    <label for="{{choice.id}}" class="txtClr">{{choice.choice}}</label>
                </div>
                {% endfor %}
            {% elif question.question_type == "checkbox" %}
            {% for choice in question.choices.all %}
                <div class="multiple-choice">
                    <input type="checkbox" name="{{question.id}}" id="{{choice.id}}" {% if question.required %} required {% endif %} value="{{choice.id}}">
                    <label for="{{choice.id}}" class="txtClr">{{choice.choice}}</label>
                </div>
                {% endfor %}
            {% endif %}
        </div>
        {% endfor %}
        <div class="margin-top-bottom">
            <input type="submit" value="Submit" class="btn btn-submit">
        </div>
    </form>
    {% if user == form.creator %}
        <a href="{% url 'edit_form' form.code %}">
            <img src="{% static 'Icon/question.png' %}" alt="Edit Question" title="Edit this form" class="edit-form-link">
        </a>
    {% endif %}
</div>
{% endblock %}

================================================
FILE: index/templatetags/count.py
================================================
from django import template
register = template.Library()

@register.filter
def count(array):
    return len(array)

================================================
FILE: index/templatetags/generate_color.py
================================================
from django import template
import random
register = template.Library()

@register.filter
def generate_color(_):
    return f"rgb({random.randint(0, 255)},{random.randint(0, 255)},{random.randint(0, 255)})"

================================================
FILE: index/templatetags/get_property.py
================================================
from django import template
register = template.Library()

@register.filter
def get_property(array, index):
    return array[index]

================================================
FILE: index/templatetags/get_response.py
================================================
from django import template
register = template.Library()

@register.filter
def get_response(responses, pk):
    return responses.response.get(answer_to__pk = pk).answer

================================================
FILE: index/templatetags/is_response.py
================================================
from django import template
register = template.Library()

@register.filter
def get_responses(responses, pk):
    return responses.response.filter(answer_to__pk = pk)

@register.filter
def is_response(responses, pk):
    for i in responses:
        if int(i.answer) == int(pk):
            return True
    return False


================================================
FILE: index/templatetags/score.py
================================================
from django import template
register = template.Library()

@register.filter
def score(responses, question):
    response = responses.response.filter(answer_to__pk = question)
    for i in response:
        if i.answer_to.question_type == "short" or i.answer_to.question_type == "paragraph":
            if i.answer == i.answer_to.answer_key: return i.answer_to.score
            else: return 0
        elif i.answer_to.question_type == "multiple choice":
            answerKey = None
            for j in i.answer_to.choices.all():
                if j.is_answer: answerKey = j.id
            if answerKey is not None and int(answerKey) == int(i.answer): return i.answer_to.score
            else: return 0
        elif i.answer_to.question_type == "checkbox":
            answers = []
            answer_keys = []
            for j in responses.response.filter(answer_to__pk = i.answer_to.pk):
                answers.append(int(j.answer))
                for k in j.answer_to.choices.all():
                    if k.is_answer and k.pk not in answer_keys: answer_keys.append(k.pk)
            if answers == answer_keys: return i.answer_to.score
            else: return 0

================================================
FILE: index/templatetags/to_int.py
================================================
from django import template
register = template.Library()

@register.filter
def to_int(number):
    return int(number)

================================================
FILE: index/tests.py
================================================
from django.test import TestCase

# Create your tests here.


================================================
FILE: index/urls.py
================================================
from django.urls import path
from . import views

urlpatterns = [
    path('', views.index, name="index"),
    path('login', views.login_view, name="login"),
    path('register', views.register, name="register"),
    path('form/<str:code>/export_csv', views.exportcsv,name='export_csv'), 
    path('logout', views.logout_view, name="logout"),
    path('form/create', views.create_form, name="create_form"),
    path('form/create/contact', views.contact_form_template, name="contact_form_template"),
    path('form/create/feedback', views.customer_feedback_template, name="customer_feedback_template"),
    path('form/create/event', views.event_registration_template, name="event_registration_template"),
    path('form/<str:code>/edit', views.edit_form, name="edit_form"),
    path('form/<str:code>/edit_title', views.edit_title, name="edit_title"),
    path('form/<str:code>/edit_description', views.edit_description, name="edit_description"),
    path('form/<str:code>/edit_background_color', views.edit_bg_color, name="edit_background_color"),
    path('form/<str:code>/edit_text_color', views.edit_text_color, name="edit_text_color"),
    path('form/<str:code>/edit_setting', views.edit_setting, name="edit_setting"),
    path('form/<str:code>/delete', views.delete_form, name="delete_form"),
    path('form/<str:code>/edit_question', views.edit_question, name="edit_question"),
    path('form/<str:code>/edit_choice', views.edit_choice, name="edit_choice"),
    path('form/<str:code>/add_choice', views.add_choice, name="add_choice"),
    path('form/<str:code>/remove_choice', views.remove_choice, name="remove_choice"),
    path('form/<str:code>/get_choice/<str:question>', views.get_choice, name="get_choice"),
    path('form/<str:code>/add_question', views.add_question, name="add_question"),
    path('form/<str:code>/delete_question/<str:question>', views.delete_question, name="delete_question"),
    path('form/<str:code>/score', views.score, name="score"),
    path('form/<str:code>/edit_score', views.edit_score, name="edit_score"),
    path('form/<str:code>/answer_key', views.answer_key, name="answer_key"),
    path('form/<str:code>/feedback', views.feedback, name="feedback"),
    path('form/<str:code>/viewform', views.view_form, name="view_form"),
    path('form/<str:code>/submit', views.submit_form, name="submit_form"),
    path('form/<str:code>/responses', views.responses, name='responses'),
    path('form/<str:code>/response/<str:response_code>', views.response, name="response"),
    path('form/<str:code>/response/<str:response_code>/edit', views.edit_response, name="edit_response"),
    path('form/<str:code>/responses/delete', views.delete_responses, name="delete_responses"),
    path('403', views.FourZeroThree, name="403"),
    path('404', views.FourZeroFour, name="404")
]

================================================
FILE: index/views.py
================================================
from django.shortcuts import render
from django.http import HttpResponse, HttpResponseRedirect, JsonResponse
from django.db import IntegrityError
from django.urls import reverse
from django.contrib.auth import authenticate, login, logout
from .models import User, Choices, Questions, Answer, Form, Responses
from django.core import serializers
import json
import random
import string
import csv

# Create your views here.
def index(request):
    if not request.user.is_authenticated:
        return HttpResponseRedirect(reverse('login'))
    forms = Form.objects.filter(creator = request.user)
    return render(request, "index/index.html", {
        "forms": forms
    })

def login_view(request):
    #Check if the user is logged in
    if request.user.is_authenticated:
        return HttpResponseRedirect(reverse('index'))
    if request.method == "POST":
        username = request.POST["username"].lower()
        password = request.POST["password"]
        user = authenticate(request, username = username, password = password)
        # if user authentication success
        if user is not None:
            login(request, user)
            return HttpResponseRedirect(reverse('index'))
        else:
            return render(request, "index/login.html", {
                "message": "Invalid username and/or password"
            })
    return render(request, "index/login.html")

def register(request):
    #Check if the user is logged in
    if request.user.is_authenticated:
        return HttpResponseRedirect(reverse('index'))
    if request.method == "POST":
        username = request.POST["username"].lower()
        password = request.POST["password"]
        email = request.POST["email"]
        confirmation = request.POST["confirmation"]
        #check if the password is the same as confirmation
        if password != confirmation:
            return render(request, "index/register.html", {
                "message": "Passwords must match."
            })
        #Checks if the username is already in use
        if User.objects.filter(email = email).count() == 1:
            return render(request, "index/register.html", {
                "message": "Email already taken."
            })
        try:
            user = User.objects.create_user(username = username, password = password, email = email)
            user.save()
            login(request, user)
            return HttpResponseRedirect(reverse('index'))
        except IntegrityError:
            return render(request, "index/register.html", {
                "message": "Username already taken"
            })
    return render(request, "index/register.html")


def logout_view(request):
    #Logout the user
    logout(request)
    return HttpResponseRedirect(reverse('index'))

def create_form(request):
    # Creator must be authenticated
    if not request.user.is_authenticated:
        return HttpResponseRedirect(reverse("login"))
    # Create a blank form API
    if request.method == "POST":
        data = json.loads(request.body)
        title = data["title"]
        code = ''.join(random.choice(string.ascii_letters + string.digits) for x in range(30))
        choices = Choices(choice = "Option 1")
        choices.save()
        question = Questions(question_type = "multiple choice", question= "Untitled Question", required= False)
        question.save()
        question.choices.add(choices)
        question.save()
        form = Form(code = code, title = title, creator=request.user)
        form.save()
        form.questions.add(question)
        form.save()
        return JsonResponse({"message": "Sucess", "code": code})

def edit_form(request, code):
    if not request.user.is_authenticated:
        return HttpResponseRedirect(reverse("login"))
    formInfo = Form.objects.filter(code = code)
    #Checking if form exists
    if formInfo.count() == 0:
        return HttpResponseRedirect(reverse("404"))
    else: formInfo = formInfo[0]
    #Checking if form creator is user
    if formInfo.creator != request.user:
        return HttpResponseRedirect(reverse("403"))
    return render(request, "index/form.html", {
        "code": code,
        "form": formInfo
    })

def edit_title(request, code):
    if not request.user.is_authenticated:
        return HttpResponseRedirect(reverse("login"))
    formInfo = Form.objects.filter(code = code)
    #Checking if form exists
    if formInfo.count() == 0:
        return HttpResponseRedirect(reverse("404"))
    else: formInfo = formInfo[0]
    #Checking if form creator is user
    if formInfo.creator != request.user:
        return HttpResponseRedirect(reverse("403"))
    if request.method == "POST":
        data = json.loads(request.body)
        if len(data["title"]) > 0:
            formInfo.title = data["title"]
            formInfo.save()
        else:
            formInfo.title = formInfo.title[0]
            formInfo.save()
        return JsonResponse({"message": "Success", "title": formInfo.title})

def edit_description(request, code):
    if not request.user.is_authenticated:
        return HttpResponseRedirect(reverse("login"))
    formInfo = Form.objects.filter(code = code)
    #Checking if form exists
    if formInfo.count() == 0:
        return HttpResponseRedirect(reverse("404"))
    else: formInfo = formInfo[0]
    #Checking if form creator is user
    if formInfo.creator != request.user:
        return HttpResponseRedirect(reverse("403"))
    if request.method == "POST":
        data = json.loads(request.body)
        formInfo.description = data["description"]
        formInfo.save()
        return JsonResponse({"message": "Success", "description": formInfo.description})

def edit_bg_color(request, code):
    if not request.user.is_authenticated:
        return HttpResponseRedirect(reverse("login"))
    formInfo = Form.objects.filter(code = code)
    #Checking if form exists
    if formInfo.count() == 0:
        return HttpResponseRedirect(reverse("404"))
    else: formInfo = formInfo[0]
    #Checking if form creator is user
    if formInfo.creator != request.user:
        return HttpResponseRedirect(reverse("403"))
    if request.method == "POST":
        data = json.loads(request.body)
        formInfo.background_color = data["bgColor"]
        formInfo.save()
        return JsonResponse({"message": "Success", "bgColor": formInfo.background_color})

def edit_text_color(request, code):
    if not request.user.is_authenticated:
        return HttpResponseRedirect(reverse("login"))
    formInfo = Form.objects.filter(code = code)
    #Checking if form exists
    if formInfo.count() == 0:
        return HttpResponseRedirect(reverse("404"))
    else: formInfo = formInfo[0]
    #Checking if form creator is user
    if formInfo.creator != request.user:
        return HttpResponseRedirect(reverse("403"))
    if request.method == "POST":
        data = json.loads(request.body)
        formInfo.text_color = data["textColor"]
        formInfo.save()
        return JsonResponse({"message": "Success", "textColor": formInfo.text_color})

def edit_setting(request, code):
    if not request.user.is_authenticated:
        return HttpResponseRedirect(reverse("login"))
    formInfo = Form.objects.filter(code = code)
    #Checking if form exists
    if formInfo.count() == 0:
        return HttpResponseRedirect(reverse("404"))
    else: formInfo = formInfo[0]
    #Checking if form creator is user
    if formInfo.creator != request.user:
        return HttpResponseRedirect(reverse("403"))
    if request.method == "POST":
        data = json.loads(request.body)
        formInfo.collect_email = data["collect_email"]
        formInfo.is_quiz = data["is_quiz"]
        formInfo.authenticated_responder = data["authenticated_responder"]
        formInfo.confirmation_message = data["confirmation_message"]
        formInfo.edit_after_submit = data["edit_after_submit"]
        formInfo.allow_view_score = data["allow_view_score"]
        formInfo.save()
        return JsonResponse({'message': "Success"})

def delete_form(request, code):
    if not request.user.is_authenticated:
        return HttpResponseRedirect(reverse("login"))
    formInfo = Form.objects.filter(code = code)
    #Checking if form exists
    if formInfo.count() == 0:
        return HttpResponseRedirect(reverse("404"))
    else: formInfo = formInfo[0]
    #Checking if form creator is user
    if formInfo.creator != request.user:
        return HttpResponseRedirect(reverse("403"))
    if request.method == "DELETE":
        #Delete all questions and choices
        for i in formInfo.questions.all():
            for j in i.choices.all():
                j.delete()
            i.delete()
        for i in Responses.objects.filter(response_to = formInfo):
            for j in i.response.all():
                j.delete()
            i.delete()
        formInfo.delete()
        return JsonResponse({'message': "Success"})

def edit_question(request, code):
    if not request.user.is_authenticated:
        return HttpResponseRedirect(reverse("login"))
    formInfo = Form.objects.filter(code = code)
    #Checking if form exists
    if formInfo.count() == 0:
        return HttpResponseRedirect(reverse('404'))
    else: formInfo = formInfo[0]
    #Checking if form creator is user
    if formInfo.creator != request.user:
        return HttpResponseRedirect(reverse("403"))
    if request.method == "POST":
        data = json.loads(request.body)
        question_id = data["id"]
        question = Questions.objects.filter(id = question_id)
        if question.count() == 0:
            return HttpResponseRedirect(reverse("404"))
        else: question = question[0]
        question.question = data["question"]
        question.question_type = data["question_type"]
        question.required = data["required"]
        if(data.get("score")): question.score = data["score"]
        if(data.get("answer_key")): question.answer_key = data["answer_key"]
        question.save()
        return JsonResponse({'message': "Success"})

def edit_choice(request, code):
    if not request.user.is_authenticated:
        return HttpResponseRedirect(reverse("login"))
    formInfo = Form.objects.filter(code = code)
    #Checking if form exists
    if formInfo.count() == 0:
        return HttpResponseRedirect(reverse('404'))
    else: formInfo = formInfo[0]
    #Checking if form creator is user
    if formInfo.creator != request.user:
        return HttpResponseRedirect(reverse("403"))
    if request.method == "POST":
        data = json.loads(request.body)
        choice_id = data["id"]
        choice = Choices.objects.filter(id = choice_id)
        if choice.count() == 0:
            return HttpResponseRedirect(reverse("404"))
        else: choice = choice[0]
        choice.choice = data["choice"]
        if(data.get('is_answer')): choice.is_answer = data["is_answer"]
        choice.save()
        return JsonResponse({'message': "Success"})

def add_choice(request, code):
    if not request.user.is_authenticated:
        return HttpResponseRedirect(reverse("login"))
    formInfo = Form.objects.filter(code = code)
    #Checking if form exists
    if formInfo.count() == 0:
        return HttpResponseRedirect(reverse('404'))
    else: formInfo = formInfo[0]
    #Checking if form creator is user
    if formInfo.creator != request.user:
        return HttpResponseRedirect(reverse("403"))
    if request.method == "POST":
        data = json.loads(request.body)
        choice = Choices(choice="Option")
        choice.save()
        formInfo.questions.get(pk = data["question"]).choices.add(choice)
        formInfo.save()
        return JsonResponse({"message": "Success", "choice": choice.choice, "id": choice.id})

def remove_choice(request, code):
    if not request.user.is_authenticated:
        return HttpResponseRedirect(reverse("login"))
    formInfo = Form.objects.filter(code = code)
    #Checking if form exists
    if formInfo.count() == 0:
        return HttpResponseRedirect(reverse('404'))
    else: formInfo = formInfo[0]
    #Checking if form creator is user
    if formInfo.creator != request.user:
        return HttpResponseRedirect(reverse("403"))
    if request.method == "POST":
        data = json.loads(request.body)
        choice = Choices.objects.filter(pk = data["id"])
        if choice.count() == 0:
            return HttpResponseRedirect(reverse("404"))
        else: choice = choice[0]
        choice.delete()
        return JsonResponse({"message": "Success"})

def get_choice(request, code, question):
    if not request.user.is_authenticated:
        return HttpResponseRedirect(reverse("login"))
    formInfo = Form.objects.filter(code = code)
    #Checking if form exists
    if formInfo.count() == 0:
        return HttpResponseRedirect(reverse('404'))
    else: formInfo = formInfo[0]
    #Checking if form creator is user
    if formInfo.creator != request.user:
        return HttpResponseRedirect(reverse("403"))
    if request.method == "GET":
        question = Questions.objects.filter(id = question)
        if question.count() == 0: return HttpResponseRedirect(reverse('404'))
        else: question = question[0]
        choices = question.choices.all()
        choices = [{"choice":i.choice, "is_answer":i.is_answer, "id": i.id} for i in choices]
        return JsonResponse({"choices": choices, "question": question.question, "question_type": question.question_type, "question_id": question.id})

def add_question(request, code):
    if not request.user.is_authenticated:
        return HttpResponseRedirect(reverse("login"))
    formInfo = Form.objects.filter(code = code)
    #Checking if form exists
    if formInfo.count() == 0:
        return HttpResponseRedirect(reverse('404'))
    else: formInfo = formInfo[0]
    #Checking if form creator is user
    if formInfo.creator != request.user:
        return HttpResponseRedirect(reverse("403"))
    if request.method == "POST":
        choices = Choices(choice = "Option 1")
        choices.save()
        question = Questions(question_type = "multiple choice", question= "Untitled Question", required= False)
        question.save()
        question.choices.add(choices)
        question.save()
        formInfo.questions.add(question)
        formInfo.save()
        return JsonResponse({'question': {'question': "Untitled Question", "question_type": "multiple choice", "required": False, "id": question.id}, 
        "choices": {"choice": "Option 1", "is_answer": False, 'id': choices.id}})

def delete_question(request, code, question):
    if not request.user.is_authenticated:
        return HttpResponseRedirect(reverse("login"))
    formInfo = Form.objects.filter(code = code)
    #Checking if form exists
    if formInfo.count() == 0:
        return HttpResponseRedirect(reverse('404'))
    else: formInfo = formInfo[0]
    #Checking if form creator is user
    if formInfo.creator != request.user:
        return HttpResponseRedirect(reverse("403"))
    if request.method == "DELETE":
        question = Questions.objects.filter(id = question)
        if question.count() == 0: return HttpResponseRedirect(reverse("404"))
        else: question = question[0]
        for i in question.choices.all():
            i.delete()
            question.delete()
        return JsonResponse({"message": "Success"})

def score(request, code):
    if not request.user.is_authenticated:
        return HttpResponseRedirect(reverse("login"))
    formInfo = Form.objects.filter(code = code)
    #Checking if form exists
    if formInfo.count() == 0:
        return HttpResponseRedirect(reverse('404'))
    else: formInfo = formInfo[0]
    #Checking if form creator is user
    if formInfo.creator != request.user:
        return HttpResponseRedirect(reverse("403"))
    if not formInfo.is_quiz:
        return HttpResponseRedirect(reverse("edit_form", args = [code]))
    else:
        return render(request, "index/score.html", {
            "form": formInfo
        })

def edit_score(request, code):
    if not request.user.is_authenticated:
        return HttpResponseRedirect(reverse("login"))
    formInfo = Form.objects.filter(code = code)
    #Checking if form exists
    if formInfo.count() == 0:
        return HttpResponseRedirect(reverse('404'))
    else: formInfo = formInfo[0]
    #Checking if form creator is user
    if formInfo.creator != request.user:
        return HttpResponseRedirect(reverse("403"))
    if not formInfo.is_quiz:
        return HttpResponseRedirect(reverse("edit_form", args = [code]))
    else:
        if request.method == "POST":
            data = json.loads(request.body)
            question_id = data["question_id"]
            question = formInfo.questions.filter(id = question_id)
            if question.count() == 0:
                return HttpResponseRedirect(reverse("edit_form", args = [code]))
            else: question = question[0]
            score = data["score"]
            if score == "": score = 0
            question.score = score
            question.save()
            return JsonResponse({"message": "Success"})

def answer_key(request, code):
    if not request.user.is_authenticated:
        return HttpResponseRedirect(reverse("login"))
    formInfo = Form.objects.filter(code = code)
    #Checking if form exists
    if formInfo.count() == 0:
        return HttpResponseRedirect(reverse('404'))
    else: formInfo = formInfo[0]
    #Checking if form creator is user
    if formInfo.creator != request.user:
        return HttpResponseRedirect(reverse("403"))
    if not formInfo.is_quiz:
        return HttpResponseRedirect(reverse("edit_form", args = [code]))
    else:
        if request.method == "POST":
            data = json.loads(request.body)
            question = Questions.objects.filter(id = data["question_id"])
            if question.count() == 0: return HttpResponseRedirect(reverse("edit_form", args = [code]))
            else: question = question[0]
            if question.question_type == "short" or question.question_type == "paragraph":
                question.answer_key = data["answer_key"]
                question.save()
            else:
                for i in question.choices.all():
                    i.is_answer = False
                    i.save()
                if question.question_type == "multiple choice":
                    choice = question.choices.get(pk = data["answer_key"])
                    choice.is_answer = True
                    choice.save()
                else:
                    for i in data["answer_key"]:
                        choice = question.choices.get(id = i)
                        choice.is_answer = True
                        choice.save()
                question.save()
            return JsonResponse({'message': "Success"})

def feedback(request, code):
    if not request.user.is_authenticated:
        return HttpResponseRedirect(reverse("login"))
    formInfo = Form.objects.filter(code = code)
    #Checking if form exists
    if formInfo.count() == 0:
        return HttpResponseRedirect(reverse('404'))
    else: formInfo = formInfo[0]
    #Checking if form creator is user
    if formInfo.creator != request.user:
        return HttpResponseRedirect(reverse("403"))
    if not formInfo.is_quiz:
        return HttpResponseRedirect(reverse("edit_form", args = [code]))
    else:
        if request.method == "POST":
            data = json.loads(request.body)
            question = formInfo.questions.get(id = data["question_id"])
            question.feedback = data["feedback"]
            question.save()
            return JsonResponse({'message': "Success"})

def view_form(request, code):
    formInfo = Form.objects.filter(code = code)
    #Checking if form exists
    if formInfo.count() == 0:
        return HttpResponseRedirect(reverse('404'))
    else: formInfo = formInfo[0]
    if formInfo.authenticated_responder:
        if not request.user.is_authenticated:
            return HttpResponseRedirect(reverse("login"))
    return render(request, "index/view_form.html", {
        "form": formInfo
    })

def get_client_ip(request):
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    if x_forwarded_for:
        ip = x_forwarded_for.split(',')[0]
    else:
        ip = request.META.get('REMOTE_ADDR')
    return ip

def submit_form(request, code):
    formInfo = Form.objects.filter(code = code)
    #Checking if form exists
    if formInfo.count() == 0:
        return HttpResponseRedirect(reverse('404'))
    else: formInfo = formInfo[0]
    if formInfo.authenticated_responder:
        if not request.user.is_authenticated:
            return HttpResponseRedirect(reverse("login"))
    if request.method == "POST":
        code = ''.join(random.choice(string.ascii_letters + string.digits) for x in range(20))
        if formInfo.authenticated_responder:
            response = Responses(response_code = code, response_to = formInfo, responder_ip = get_client_ip(request), responder = request.user)
            response.save()
        else:
            if not formInfo.collect_email:
                response = Responses(response_code = code, response_to = formInfo, responder_ip = get_client_ip(request))
                response.save()
            else:
                response = Responses(response_code = code, response_to = formInfo, responder_ip = get_client_ip(request), responder_email=request.POST["email-address"])
                response.save()
        for i in request.POST:
            #Excluding csrf token
            if i == "csrfmiddlewaretoken" or i == "email-address":
                continue
            question = formInfo.questions.get(id = i)
            for j in request.POST.getlist(i):
                answer = Answer(answer=j, answer_to = question)
                answer.save()
                response.response.add(answer)
                response.save()
        return render(request, "index/form_response.html", {
            "form": formInfo,
            "code": code
        })

def responses(request, code):
    if not request.user.is_authenticated:
        return HttpResponseRedirect(reverse("login"))
    formInfo = Form.objects.filter(code = code)
    #Checking if form exists
    if formInfo.count() == 0:
        return HttpResponseRedirect(reverse('404'))
    else: formInfo = formInfo[0]

    responsesSummary = []
    choiceAnswered = {}
    filteredResponsesSummary = {}
    for question in formInfo.questions.all():
        answers = Answer.objects.filter(answer_to = question.id)
        if question.question_type == "multiple choice" or question.question_type == "checkbox":
            choiceAnswered[question.question] = choiceAnswered.get(question.question, {})
            for answer in answers:
                choice = answer.answer_to.choices.get(id = answer.answer).choice
                choiceAnswered[question.question][choice] = choiceAnswered.get(question.question, {}).get(choice, 0) + 1
        responsesSummary.append({"question": question, "answers":answers })
    for answr in choiceAnswered:
        filteredResponsesSummary[answr] = {}
        keys = choiceAnswered[answr].values()
        for choice in choiceAnswered[answr]:
            filteredResponsesSummary[answr][choice] = choiceAnswered[answr][choice]
    #Checking if form creator is user
    if formInfo.creator != request.user:
        return HttpResponseRedirect(reverse("403"))
    return render(request, "index/responses.html", {
        "form": formInfo,
        "responses": Responses.objects.filter(response_to = formInfo),
        "responsesSummary": responsesSummary,
        "filteredResponsesSummary": filteredResponsesSummary
    })

def retrieve_checkbox_choices(response, question):
    checkbox_answers = []

    answers = Answer.objects.filter(answer_to=question, response=response)
    for answer in answers:
        selected_choice_ids = answer.answer.split(',')  # Split the string into individual choice IDs
        selected_choices = Choices.objects.filter(pk__in=selected_choice_ids)
        checkbox_answers.append([choice.choice for choice in selected_choices])

    return checkbox_answers



def exportcsv(request,code):
    formInfo = Form.objects.filter(code = code)
    formInfo = formInfo[0]
    responses=Responses.objects.filter(response_to = formInfo)
    questions = formInfo.questions.all()


    http_response = HttpResponse()
    http_response['Content-Disposition'] = f'attachment; filename= {formInfo.title}.csv'
    writer = csv.writer(http_response)
    header = ['Response Code', 'Responder', 'Responder Email','Responder_ip']
    
    for question in questions:
        header.append(question.question)
    
    writer.writerow(header)

    for response in responses:
        response_data = [
        response.response_code,
        response.responder.username if response.responder else 'Anonymous',
        response.responder_email if response.responder_email else '',
        response.responder_ip if response.responder_ip else ''
    ]
        for question in questions:
            answer = Answer.objects.filter(answer_to=question, response=response).first()
            
        
            if  question.question_type not in ['multiple choice','checkbox']:
                response_data.append(answer.answer if answer else '')
            elif question.question_type == "multiple choice":
                response_data.append(answer.answer_to.choices.get(id = answer.answer).choice if answer else '')
            elif question.question_type == "checkbox":
                if answer and question.question_type == 'checkbox':
                    checkbox_choices = retrieve_checkbox_choices(response,answer.answer_to)
                    response_data.append(checkbox_choices)

        print(response_data)
        writer.writerow(response_data)
        
    return http_response

def response(request, code, response_code):
    formInfo = Form.objects.filter(code = code)
    #Checking if form exists
    if formInfo.count() == 0:
        return HttpResponseRedirect(reverse('404'))
    else: formInfo = formInfo[0]
    #Checking if form creator is user
    if not formInfo.allow_view_score:
        if formInfo.creator != request.user:
            return HttpResponseRedirect(reverse("403"))
    total_score = 0
    score = 0
    responseInfo = Responses.objects.filter(response_code = response_code)
    if responseInfo.count() == 0:
        return HttpResponseRedirect(reverse('404'))
    else: responseInfo = responseInfo[0]
    if formInfo.is_quiz:
        for i in formInfo.questions.all():
            total_score += i.score
        for i in responseInfo.response.all():
            if i.answer_to.question_type == "short" or i.answer_to.question_type == "paragraph":
                if i.answer == i.answer_to.answer_key: score += i.answer_to.score
            elif i.answer_to.question_type == "multiple choice":
                answerKey = None
                for j in i.answer_to.choices.all():
                    if j.is_answer: answerKey = j.id
                if answerKey is not None and int(answerKey) == int(i.answer):
                    score += i.answer_to.score
        _temp = []
        for i in responseInfo.response.all():
            if i.answer_to.question_type == "checkbox" and i.answer_to.pk not in _temp:
                answers = []
                answer_keys = []
                for j in responseInfo.response.filter(answer_to__pk = i.answer_to.pk):
                    answers.append(int(j.answer))
                    for k in j.answer_to.choices.all():
                        if k.is_answer and k.pk not in answer_keys: answer_keys.append(k.pk)
                    _temp.append(i.answer_to.pk)
                if answers == answer_keys: score += i.answer_to.score
    return render(request, "index/response.html", {
        "form": formInfo,
        "response": responseInfo,
        "score": score,
        "total_score": total_score
    })

def edit_response(request, code, response_code):
    formInfo = Form.objects.filter(code = code)
    #Checking if form exists
    if formInfo.count() == 0:
        return HttpResponseRedirect(reverse('404'))
    else: formInfo = formInfo[0]
    response = Responses.objects.filter(response_code = response_code, response_to = formInfo)
    if response.count() == 0:
        return HttpResponseRedirect(reverse('404'))
    else: response = response[0]
    if formInfo.authenticated_responder:
        if not request.user.is_authenticated:
            return HttpResponseRedirect(reverse("login"))
        if response.responder != request.user:
            return HttpResponseRedirect(reverse('403'))
    if request.method == "POST":
        if formInfo.authenticated_responder and not response.responder:
            response.responder = request.user
            response.save()
        if formInfo.collect_email:
            response.responder_email = request.POST["email-address"]
            response.save()
        #Deleting all existing answers
        for i in response.response.all():
            i.delete()
        for i in request.POST:
            #Excluding csrf token and email address
            if i == "csrfmiddlewaretoken" or i == "email-address":
                continue
            question = formInfo.questions.get(id = i)
            for j in request.POST.getlist(i):
                answer = Answer(answer=j, answer_to = question)
                answer.save()
                response.response.add(answer)
                response.save()
        if formInfo.is_quiz:
            return HttpResponseRedirect(reverse("response", args = [formInfo.code, response.response_code]))
        else:
            return render(request, "index/form_response.html", {
                "form": formInfo,
                "code": response.response_code
            })
    return render(request, "index/edit_response.html", {
        "form": formInfo,
        "response": response
    })

def contact_form_template(request):
    # Creator must be authenticated
    if not request.user.is_authenticated:
        return HttpResponseRedirect(reverse("login"))
    # Create a blank form API
    if request.method == "POST":
        code = ''.join(random.choice(string.ascii_letters + string.digits) for x in range(30))
        name = Questions(question_type = "short", question= "Name", required= True)
        name.save()
        email = Questions(question_type="short", question = "Email", required = True)
        email.save()
        address = Questions(question_type="paragraph", question="Address", required = True)
        address.save()
        phone = Questions(question_type="short", question="Phone number", required = False)
        phone.save()
        comments = Questions(question_type = "paragraph", question = "Comments", required = False)
        comments.save()
        form = Form(code = code, title = "Contact information", creator=request.user, background_color="#e2eee0", allow_view_score = False, edit_after_submit = True)
        form.save()
        form.questions.add(name)
        form.questions.add(email)
        form.questions.add(address)
        form.questions.add(phone)
        form.questions.add(comments)
        form.save()
        return JsonResponse({"message": "Sucess", "code": code})

def customer_feedback_template(request):
    # Creator must be authenticated
    if not request.user.is_authenticated:
        return HttpResponseRedirect(reverse("login"))
    # Create a blank form API
    if request.method == "POST":
        code = ''.join(random.choice(string.ascii_letters + string.digits) for x in range(30))
        comment = Choices(choice = "Comments")
        comment.save()
        question = Choices(choice = "Questions")
        question.save()
        bug = Choices(choice = "Bug Reports")
        bug.save()
        feature = Choices(choice = "Feature Request")
        feature.save()
        feedback_type = Questions(question = "Feedback Type", question_type="multiple choice", required=False)
        feedback_type.save()
        feedback_type.choices.add(comment)
        feedback_type.choices.add(bug)
        feedback_type.choices.add(question)
        feedback_type.choices.add(feature)
        feedback_type.save()
        feedback = Questions(question = "Feedback", question_type="paragraph", required=True)
        feedback.save()
        suggestion = Questions(question = "Suggestions for improvement", question_type="paragraph", required=False)
        suggestion.save()
        name = Questions(question = "Name", question_type="short", required=False)
        name.save()
        email = Questions(question= "Email", question_type="short", required=False)
        email.save()
        form = Form(code = code, title = "Customer Feedback", creator=request.user, background_color="#e2eee0", confirmation_message="Thanks so much for giving us feedback!",
        description = "We would love to hear your thoughts or feedback on how we can improve your experience!", allow_view_score = False, edit_after_submit = True)
        form.save()
        form.questions.add(feedback_type)
        form.questions.add(feedback)
        form.questions.add(suggestion)
        form.questions.add(name)
        form.questions.add(email)
        return JsonResponse({"message": "Sucess", "code": code})

def event_registration_template(request):
    # Creator must be authenticated
    if not request.user.is_authenticated:
        return HttpResponseRedirect(reverse("login"))
    # Create a blank form API
    if request.method == "POST":
        code = ''.join(random.choice(string.ascii_letters + string.digits) for x in range(30))
        name = Questions(question="Name", question_type= "short", required=False)
        name.save()
        email = Questions(question = "email", question_type="short", required=True)
        email.save()
        organization = Questions(question = "Organization", question_type= "short", required=True)
        organization.save()
        day1 = Choices(choice="Day 1")
        day1.save()
        day2 = Choices(choice= "Day 2")
        day2.save()
        day3 = Choices(choice= "Day 3")
        day3.save()
        day = Questions(question="What days will you attend?", question_type="checkbox", required=True)
        day.save()
        day.choices.add(day1)
        day.choices.add(day2)
        day.choices.add(day3)
        day.save()
        dietary_none = Choices(choice="None")
        dietary_none.save()
        dietary_vegetarian = Choices(choice="Vegetarian")
        dietary_vegetarian.save()
        dietary_kosher = Choices(choice="Kosher")
        dietary_kosher.save()
        dietary_gluten = Choices(choice = "Gluten-free")
        dietary_gluten.save()
        dietary = Questions(question = "Dietary restrictions", question_type="multiple choice", required = True)
        dietary.save()
        dietary.choices.add(dietary_none)
        dietary.choices.add(dietary_vegetarian)
        dietary.choices.add(dietary_gluten)
        dietary.choices.add(dietary_kosher)
        dietary.save()
        accept_agreement = Choices(choice = "Yes")
        accept_agreement.save()
        agreement = Questions(question = "I understand that I will have to pay $$ upon arrival", question_type="checkbox", required=True)
        agreement.save()
        agreement.choices.add(accept_agreement)
        agreement.save()
        form = Form(code = code, title = "Event Registration", creator=request.user, background_color="#fdefc3", 
        confirmation_message="We have received your registration.\n\
Insert other information here.\n\
\n\
Save the link below, which can be used to edit your registration up until the registration closing date.",
        description = "Event Timing: January 4th-6th, 2016\n\
Event Address: 123 Your Street Your City, ST 12345\n\
Contact us at (123) 456-7890 or no_reply@example.com", edit_after_submit=True, allow_view_score=False)
        form.save()
        form.questions.add(name)
        form.questions.add(email)
        form.questions.add(organization)
        form.questions.add(day)
        form.questions.add(dietary)
        form.questions.add(agreement)
        form.save()
        return JsonResponse({"message": "Sucess", "code": code})

def delete_responses(request, code):
    if not request.user.is_authenticated:
        return HttpResponseRedirect(reverse("login"))
    formInfo = Form.objects.filter(code = code)
    #Checking if form exists
    if formInfo.count() == 0:
        return HttpResponseRedirect(reverse('404'))
    else: formInfo = formInfo[0]
    #Checking if form creator is user
    if formInfo.creator != request.user:
        return HttpResponseRedirect(reverse("403"))
    if request.method == "DELETE":
        responses = Responses.objects.filter(response_to = formInfo)
        for response in responses:
            for i in response.response.all():
                i.delete()
            response.delete()
        return JsonResponse({"message": "Success"})

# Error handler
def FourZeroThree(request):
    return render(request, "error/403.html")

def FourZeroFour(request):
    return render(request, "error/
Download .txt
gitextract_9q7rdef_/

├── .deepsource.toml
├── .github/
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   └── feature_request.md
│   └── dependabot.yml
├── .gitignore
├── CODE_OF_CONDUCT.md
├── Dockerfile
├── LICENSE
├── README.md
├── docker-compose.yml
├── form/
│   ├── __init__.py
│   ├── asgi.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── index/
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── migrations/
│   │   ├── 0001_initial.py
│   │   ├── 0002_auto_20201128_2040.py
│   │   ├── 0003_remove_form_see_response.py
│   │   └── __init__.py
│   ├── models.py
│   ├── static/
│   │   └── index/
│   │       ├── HurlUI.css
│   │       ├── form.js
│   │       ├── index.js
│   │       ├── response.js
│   │       ├── responses.js
│   │       ├── score.js
│   │       ├── style.css
│   │       └── viewform.js
│   ├── templates/
│   │   ├── error/
│   │   │   ├── 403.html
│   │   │   └── 404.html
│   │   └── index/
│   │       ├── edit_response.html
│   │       ├── form.html
│   │       ├── form_response.html
│   │       ├── index.html
│   │       ├── layout.html
│   │       ├── login.html
│   │       ├── register.html
│   │       ├── response.html
│   │       ├── responses.html
│   │       ├── score.html
│   │       └── view_form.html
│   ├── templatetags/
│   │   ├── count.py
│   │   ├── generate_color.py
│   │   ├── get_property.py
│   │   ├── get_response.py
│   │   ├── is_response.py
│   │   ├── score.py
│   │   └── to_int.py
│   ├── tests.py
│   ├── urls.py
│   └── views.py
├── manage.py
├── renovate.json
└── requirements.txt
Download .txt
SYMBOL INDEX (56 symbols across 14 files)

FILE: index/apps.py
  class IndexConfig (line 4) | class IndexConfig(AppConfig):

FILE: index/migrations/0001_initial.py
  class Migration (line 11) | class Migration(migrations.Migration):

FILE: index/migrations/0002_auto_20201128_2040.py
  class Migration (line 6) | class Migration(migrations.Migration):

FILE: index/migrations/0003_remove_form_see_response.py
  class Migration (line 6) | class Migration(migrations.Migration):

FILE: index/models.py
  class User (line 5) | class User(AbstractUser, models.Model):
  class Choices (line 8) | class Choices(models.Model):
  class Questions (line 12) | class Questions(models.Model):
  class Answer (line 21) | class Answer(models.Model):
  class Form (line 25) | class Form(models.Model):
  class Responses (line 42) | class Responses(models.Model):

FILE: index/templatetags/count.py
  function count (line 5) | def count(array):

FILE: index/templatetags/generate_color.py
  function generate_color (line 6) | def generate_color(_):

FILE: index/templatetags/get_property.py
  function get_property (line 5) | def get_property(array, index):

FILE: index/templatetags/get_response.py
  function get_response (line 5) | def get_response(responses, pk):

FILE: index/templatetags/is_response.py
  function get_responses (line 5) | def get_responses(responses, pk):
  function is_response (line 9) | def is_response(responses, pk):

FILE: index/templatetags/score.py
  function score (line 5) | def score(responses, question):

FILE: index/templatetags/to_int.py
  function to_int (line 5) | def to_int(number):

FILE: index/views.py
  function index (line 14) | def index(request):
  function login_view (line 22) | def login_view(request):
  function register (line 40) | def register(request):
  function logout_view (line 71) | def logout_view(request):
  function create_form (line 76) | def create_form(request):
  function edit_form (line 97) | def edit_form(request, code):
  function edit_title (line 113) | def edit_title(request, code):
  function edit_description (line 134) | def edit_description(request, code):
  function edit_bg_color (line 151) | def edit_bg_color(request, code):
  function edit_text_color (line 168) | def edit_text_color(request, code):
  function edit_setting (line 185) | def edit_setting(request, code):
  function delete_form (line 207) | def delete_form(request, code):
  function edit_question (line 231) | def edit_question(request, code):
  function edit_choice (line 257) | def edit_choice(request, code):
  function add_choice (line 280) | def add_choice(request, code):
  function remove_choice (line 299) | def remove_choice(request, code):
  function get_choice (line 319) | def get_choice(request, code, question):
  function add_question (line 338) | def add_question(request, code):
  function delete_question (line 361) | def delete_question(request, code, question):
  function score (line 381) | def score(request, code):
  function edit_score (line 399) | def edit_score(request, code):
  function answer_key (line 426) | def answer_key(request, code):
  function feedback (line 464) | def feedback(request, code):
  function view_form (line 485) | def view_form(request, code):
  function get_client_ip (line 498) | def get_client_ip(request):
  function submit_form (line 506) | def submit_form(request, code):
  function responses (line 542) | def responses(request, code):
  function retrieve_checkbox_choices (line 577) | def retrieve_checkbox_choices(response, question):
  function exportcsv (line 590) | def exportcsv(request,code):
  function response (line 632) | def response(request, code, response_code):
  function edit_response (line 678) | def edit_response(request, code, response_code):
  function contact_form_template (line 725) | def contact_form_template(request):
  function customer_feedback_template (line 752) | def customer_feedback_template(request):
  function event_registration_template (line 792) | def event_registration_template(request):
  function delete_responses (line 856) | def delete_responses(request, code):
  function FourZeroThree (line 876) | def FourZeroThree(request):
  function FourZeroFour (line 879) | def FourZeroFour(request):

FILE: manage.py
  function main (line 7) | def main():
Condensed preview — 58 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (206K chars).
[
  {
    "path": ".deepsource.toml",
    "chars": 204,
    "preview": "version = 1\n\n[[analyzers]]\nname = \"python\"\nenabled = true\n\n  [analyzers.meta]\n  runtime_version = \"3.x.x\"\n\n[[analyzers]]"
  },
  {
    "path": ".github/FUNDING.yml",
    "chars": 19,
    "preview": "ko_fi: kimlimjustin"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "chars": 834,
    "preview": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Describe the b"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "chars": 595,
    "preview": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Is your fea"
  },
  {
    "path": ".github/dependabot.yml",
    "chars": 143,
    "preview": "version: 2\nupdates:\n- package-ecosystem: pip\n  directory: \"/\"\n  schedule:\n    interval: daily\n    time: \"22:00\"\n  open-p"
  },
  {
    "path": ".gitignore",
    "chars": 44,
    "preview": "*.sqlite3\n*.sqlite3-journal\n*.pyo\n*.pyc\ndata"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "chars": 3354,
    "preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, w"
  },
  {
    "path": "Dockerfile",
    "chars": 158,
    "preview": "# syntax=docker/dockerfile:1\nFROM python:3\nENV PYTHONUNBUFFERED=1\nWORKDIR /code\nCOPY requirements.txt /code/\nRUN pip ins"
  },
  {
    "path": "LICENSE",
    "chars": 1082,
    "preview": "MIT License\n\nCopyright (c) 2020 Justin Maximillian Kimlim\n\nPermission is hereby granted, free of charge, to any person o"
  },
  {
    "path": "README.md",
    "chars": 2335,
    "preview": "# Google Forms CLONE\n\n### Demo application and feedback [here](https://google-forms-clone.herokuapp.com/form/in60XZ4GWUs"
  },
  {
    "path": "docker-compose.yml",
    "chars": 512,
    "preview": "version: \"3.9\"\n   \nservices:\n  db:\n    image: postgres\n    volumes:\n      - ./data/db:/var/lib/postgresql/data\n    envir"
  },
  {
    "path": "form/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "form/asgi.py",
    "chars": 385,
    "preview": "\"\"\"\nASGI config for form project.\n\nIt exposes the ASGI callable as a module-level variable named ``application``.\n\nFor m"
  },
  {
    "path": "form/settings.py",
    "chars": 4195,
    "preview": "\"\"\"\nDjango settings for form project.\n\nGenerated by 'django-admin startproject' using Django 3.1.3.\n\nFor more informatio"
  },
  {
    "path": "form/urls.py",
    "chars": 1002,
    "preview": "\"\"\"form URL Configuration\n\nThe `urlpatterns` list routes URLs to views. For more information please see:\n    https://doc"
  },
  {
    "path": "form/wsgi.py",
    "chars": 385,
    "preview": "\"\"\"\nWSGI config for form project.\n\nIt exposes the WSGI callable as a module-level variable named ``application``.\n\nFor m"
  },
  {
    "path": "index/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "index/admin.py",
    "chars": 63,
    "preview": "from django.contrib import admin\n\n# Register your models here.\n"
  },
  {
    "path": "index/apps.py",
    "chars": 85,
    "preview": "from django.apps import AppConfig\n\n\nclass IndexConfig(AppConfig):\n    name = 'index'\n"
  },
  {
    "path": "index/migrations/0001_initial.py",
    "chars": 6995,
    "preview": "# Generated by Django 3.1.3 on 2020-11-28 13:29\n\nfrom django.conf import settings\nimport django.contrib.auth.models\nimpo"
  },
  {
    "path": "index/migrations/0002_auto_20201128_2040.py",
    "chars": 399,
    "preview": "# Generated by Django 3.1.3 on 2020-11-28 13:40\n\nfrom django.db import migrations, models\n\n\nclass Migration(migrations.M"
  },
  {
    "path": "index/migrations/0003_remove_form_see_response.py",
    "chars": 330,
    "preview": "# Generated by Django 3.1.3 on 2020-11-28 14:58\n\nfrom django.db import migrations\n\n\nclass Migration(migrations.Migration"
  },
  {
    "path": "index/migrations/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "index/models.py",
    "chars": 2435,
    "preview": "from django.db import models\nfrom django.contrib.auth.models import AbstractUser\n\n# Create your models here.\nclass User("
  },
  {
    "path": "index/static/index/HurlUI.css",
    "chars": 5908,
    "preview": "@import url(\"https://fonts.googleapis.com/css?family=Roboto+Condensed\");\n@import url(\"https://fonts.googleapis.com/css?f"
  },
  {
    "path": "index/static/index/form.js",
    "chars": 28025,
    "preview": "document.addEventListener(\"DOMContentLoaded\", () => {\n    const csrf = Cookies.get('csrftoken');\n    document.body.style"
  },
  {
    "path": "index/static/index/index.js",
    "chars": 2152,
    "preview": "document.addEventListener(\"DOMContentLoaded\", () => {\n    document.querySelector(\"#nav-ham\").addEventListener(\"click\", ("
  },
  {
    "path": "index/static/index/response.js",
    "chars": 376,
    "preview": "document.addEventListener(\"DOMContentLoaded\", () => {\n    document.body.style.backgroundColor =  document.querySelector("
  },
  {
    "path": "index/static/index/responses.js",
    "chars": 8216,
    "preview": "document.addEventListener(\"DOMContentLoaded\", () => {\n    const csrf = Cookies.get('csrftoken');\n    document.body.style"
  },
  {
    "path": "index/static/index/score.js",
    "chars": 8592,
    "preview": "document.addEventListener(\"DOMContentLoaded\", () => {\n    const csrf = Cookies.get('csrftoken');\n    document.body.style"
  },
  {
    "path": "index/static/index/style.css",
    "chars": 12432,
    "preview": "@import url(\"https://fonts.googleapis.com/css?family=Permanent+Marker\");\n@import url(\"https://fonts.googleapis.com/css?f"
  },
  {
    "path": "index/static/index/viewform.js",
    "chars": 1536,
    "preview": "document.addEventListener(\"DOMContentLoaded\", () => {\n    document.body.style.backgroundColor =  document.querySelector("
  },
  {
    "path": "index/templates/error/403.html",
    "chars": 126,
    "preview": "{% extends 'index/layout.html' %}\n{% block body %}\n<h1 class=\"text-danger error-page\">Error 403 Forbidden.</h1>\n{% endbl"
  },
  {
    "path": "index/templates/error/404.html",
    "chars": 125,
    "preview": "{% extends 'index/layout.html' %}\n{% block body %}\n<h1 class=\"text-danger error-page\">Error 404 not found</h1>\n{% endblo"
  },
  {
    "path": "index/templates/index/edit_response.html",
    "chars": 4438,
    "preview": "{% extends 'index/layout.html' %}\n{% load static %}\n{% load get_response %}\n{% load to_int %}\n{% load is_response %}\n{% "
  },
  {
    "path": "index/templates/index/form.html",
    "chars": 13637,
    "preview": "{% extends 'index/layout.html' %}\n{% block title %}\n{{form.title}} ~ Google Forms CLONE\n{% endblock %}\n{% load static %}"
  },
  {
    "path": "index/templates/index/form_response.html",
    "chars": 997,
    "preview": "{% extends 'index/layout.html' %}\n{% load static %}\n{% block script %}\n<script src=\"{% static 'index/viewform.js' %}\" de"
  },
  {
    "path": "index/templates/index/index.html",
    "chars": 4012,
    "preview": "{% extends 'index/layout.html' %}\n{% load static %}\n{% block script %}\n<script src = \"{% static 'index/index.js' %}\" def"
  },
  {
    "path": "index/templates/index/layout.html",
    "chars": 474,
    "preview": "{% load static %}\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\""
  },
  {
    "path": "index/templates/index/login.html",
    "chars": 1106,
    "preview": "{% extends 'index/layout.html' %}\n{% block body %}\n<div class=\"container\">\n    <form class=\"box box-shadow margin-top-bo"
  },
  {
    "path": "index/templates/index/register.html",
    "chars": 1646,
    "preview": "{% extends 'index/layout.html' %}\n{% block body %}\n<div class=\"container\">\n    <form action=\"{% url 'register' %}\" metho"
  },
  {
    "path": "index/templates/index/response.html",
    "chars": 3972,
    "preview": "{% extends 'index/layout.html' %}\n{% load static %}\n{% load get_response %}\n{% load to_int %}\n{% load is_response %}\n{% "
  },
  {
    "path": "index/templates/index/responses.html",
    "chars": 12046,
    "preview": "{% extends 'index/layout.html' %}\n{% load static %}\n{% load get_property %}\n{% load generate_color %}\n{% load count %}\n{"
  },
  {
    "path": "index/templates/index/score.html",
    "chars": 11741,
    "preview": "{% extends 'index/layout.html' %}\n{% load static %}\n{% block title %}{{form.title}} ~ Google Forms CLONE{% endblock %}\n{"
  },
  {
    "path": "index/templates/index/view_form.html",
    "chars": 3317,
    "preview": "{% extends 'index/layout.html' %}\n{% load static %}\n{% block title %}{{form.title}} ~ Google Forms CLONE{% endblock %}\n{"
  },
  {
    "path": "index/templatetags/count.py",
    "chars": 115,
    "preview": "from django import template\nregister = template.Library()\n\n@register.filter\ndef count(array):\n    return len(array)"
  },
  {
    "path": "index/templatetags/generate_color.py",
    "chars": 206,
    "preview": "from django import template\nimport random\nregister = template.Library()\n\n@register.filter\ndef generate_color(_):\n    ret"
  },
  {
    "path": "index/templatetags/get_property.py",
    "chars": 131,
    "preview": "from django import template\nregister = template.Library()\n\n@register.filter\ndef get_property(array, index):\n    return a"
  },
  {
    "path": "index/templatetags/get_response.py",
    "chars": 169,
    "preview": "from django import template\nregister = template.Library()\n\n@register.filter\ndef get_response(responses, pk):\n    return "
  },
  {
    "path": "index/templatetags/is_response.py",
    "chars": 319,
    "preview": "from django import template\nregister = template.Library()\n\n@register.filter\ndef get_responses(responses, pk):\n    return"
  },
  {
    "path": "index/templatetags/score.py",
    "chars": 1172,
    "preview": "from django import template\nregister = template.Library()\n\n@register.filter\ndef score(responses, question):\n    response"
  },
  {
    "path": "index/templatetags/to_int.py",
    "chars": 118,
    "preview": "from django import template\nregister = template.Library()\n\n@register.filter\ndef to_int(number):\n    return int(number)"
  },
  {
    "path": "index/tests.py",
    "chars": 60,
    "preview": "from django.test import TestCase\n\n# Create your tests here.\n"
  },
  {
    "path": "index/urls.py",
    "chars": 2808,
    "preview": "from django.urls import path\nfrom . import views\n\nurlpatterns = [\n    path('', views.index, name=\"index\"),\n    path('log"
  },
  {
    "path": "index/views.py",
    "chars": 37187,
    "preview": "from django.shortcuts import render\nfrom django.http import HttpResponse, HttpResponseRedirect, JsonResponse\nfrom django"
  },
  {
    "path": "manage.py",
    "chars": 660,
    "preview": "#!/usr/bin/env python\n\"\"\"Django's command-line utility for administrative tasks.\"\"\"\nimport os\nimport sys\n\n\ndef main():\n "
  },
  {
    "path": "renovate.json",
    "chars": 41,
    "preview": "{\n  \"extends\": [\n    \"config:base\"\n  ]\n}\n"
  },
  {
    "path": "requirements.txt",
    "chars": 132,
    "preview": "asgiref==3.5.1\ndj-database-url==0.5.0\nDjango==4.0.2\ngunicorn==20.1.0\npsycopg2==2.9.3\npytz==2022.1\nsqlparse==0.4.2\nwhiten"
  }
]

About this extraction

This page contains the full source code of the kimlimjustin/google-form-clone GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 58 files (189.0 KB), approximately 44.1k tokens, and a symbol index with 56 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!