Commit 2604404c authored by Nipun Lakshan Perera's avatar Nipun Lakshan Perera

Code

parents
/node_modules
\ No newline at end of file
# Default ignored files
/shelf/
/workspace.xml
# CodeStream ignored files
/../../React-Admin-Template\.idea/codestream.xml
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CodeStream">
<option name="webViewContext" value="{&quot;chatProviderAccess&quot;:&quot;strict&quot;,&quot;currentTeamId&quot;:&quot;&quot;,&quot;currentStreamId&quot;:&quot;&quot;,&quot;pullRequestCheckoutBranch&quot;:false,&quot;isRepositioning&quot;:false,&quot;onboardStep&quot;:0,&quot;panelStack&quot;:[&quot;landing-redirect&quot;],&quot;hasFocus&quot;:false,&quot;channelFilter&quot;:&quot;all&quot;,&quot;channelsMuteAll&quot;:false,&quot;codemarkFileFilter&quot;:&quot;all&quot;,&quot;codemarkTypeFilter&quot;:&quot;all&quot;,&quot;codemarkTagFilter&quot;:&quot;all&quot;,&quot;codemarkBranchFilter&quot;:&quot;all&quot;,&quot;codemarkAuthorFilter&quot;:&quot;all&quot;,&quot;codemarksFileViewStyle&quot;:&quot;inline&quot;,&quot;codemarksShowArchived&quot;:false,&quot;codemarksShowResolved&quot;:false,&quot;codemarksWrapComments&quot;:false,&quot;showFeedbackSmiley&quot;:true,&quot;route&quot;:{&quot;name&quot;:&quot;newUserEntry&quot;,&quot;params&quot;:{}},&quot;spatialViewShowPRComments&quot;:false,&quot;currentPullRequestNeedsRefresh&quot;:{&quot;needsRefresh&quot;:false,&quot;providerId&quot;:&quot;&quot;,&quot;pullRequestId&quot;:&quot;&quot;},&quot;__teamless__&quot;:{&quot;selectedRegion&quot;:&quot;us&quot;},&quot;sessionStart&quot;:1668704484957}" />
</component>
</project>
\ No newline at end of file
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.9" project-jdk-type="Python SDK" />
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/React-Admin-Template.iml" filepath="$PROJECT_DIR$/.idea/React-Admin-Template.iml" />
</modules>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
\ No newline at end of file
"""
Django settings for app project.
Generated by 'django-admin startproject' using Django 2.2.8.
For more information on this file, see
https://docs.djangoproject.com/en/2.2/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.2/ref/settings/
"""
import os
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'jnbty*(xl$zl1xu63f2t9sxg3n4kl$pc75mpl$0tef)b*87&*l'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'corsheaders',
'core',
'staff',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'app.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 = 'app.wsgi.application'
# Database
# https://docs.djangoproject.com/en/2.2/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db1.sqlite3'),
}
}
# Password validation
# https://docs.djangoproject.com/en/2.2/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',
},
]
# Internationalization
# https://docs.djangoproject.com/en/2.2/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/2.2/howto/static-files/
STATIC_URL = '/static/'
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
AUTH_USER_MODEL = 'core.User'
CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_CREDENTIALS = True
"""app 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
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('core.urls')),
path('staffapi/', include('staff.urls')),
]
"""
WSGI config for app 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/2.2/howto/deployment/wsgi/
"""
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'app.settings')
application = get_wsgi_application()
from django.contrib import admin
# Register your models here.
from django.apps import AppConfig
class CoreConfig(AppConfig):
name = 'core'
import jwt, datetime
from rest_framework import exceptions
def create_access_token(id):
return jwt.encode({
'user_id': id,
'exp': datetime.datetime.utcnow() + datetime.timedelta(seconds=30),
'iat': datetime.datetime.utcnow()
}, 'access_secret', algorithm='HS256')
def decode_access_token(token):
try:
payload = jwt.decode(token, 'access_secret', algorithms='HS256')
return payload['user_id']
except:
raise exceptions.AuthenticationFailed('unauthenticated')
def create_refresh_token(id):
return jwt.encode({
'user_id': id,
'exp': datetime.datetime.utcnow() + datetime.timedelta(days=7),
'iat': datetime.datetime.utcnow()
}, 'refresh_secret', algorithm='HS256')
def decode_refresh_token(token):
try:
payload = jwt.decode(token, 'refresh_secret', algorithms='HS256')
return payload['user_id']
except:
raise exceptions.AuthenticationFailed('unauthenticated')
\ No newline at end of file
from rest_framework.views import exception_handler
def status_code_handler(exc, context):
response = exception_handler(exc, context)
if response is not None and response.status_code == 403:
response.status_code = 401
return response
\ No newline at end of file
# Generated by Django 3.0.8 on 2022-10-08 19:13
import django.contrib.auth.models
from django.db import migrations, models
import django.utils.timezone
class Migration(migrations.Migration):
initial = True
dependencies = [
('auth', '0011_update_proxy_permissions'),
]
operations = [
migrations.CreateModel(
name='Appointment',
fields=[
('id', models.AutoField(primary_key=True, serialize=False)),
('fullName', models.CharField(max_length=100)),
('gender', models.CharField(choices=[('1', 'One'), ('2', 'Two'), ('3', 'Three')], max_length=300)),
('email', models.CharField(max_length=255)),
('doctorName', models.CharField(max_length=255)),
('appointmentTime', models.DateTimeField()),
],
),
migrations.CreateModel(
name='User',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('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')),
('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')),
('name', models.CharField(max_length=255)),
('email', models.CharField(max_length=255, unique=True)),
('password', models.CharField(max_length=255)),
('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()),
],
),
]
# Generated by Django 3.0.8 on 2022-10-08 20:51
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('core', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='File',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('file', models.FileField(upload_to='')),
],
),
]
# Generated by Django 3.0.8 on 2022-10-10 06:29
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('core', '0002_file'),
]
operations = [
migrations.CreateModel(
name='specificAppointment',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('email', models.CharField(max_length=100)),
],
),
]
import email
from django.contrib.auth.models import AbstractUser
from django.db import models
class User(AbstractUser):
name = models.CharField(max_length=255)
email = models.CharField(max_length=255, unique=True)
password = models.CharField(max_length=255)
first_name = None
last_name = None
username = None
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
genderChoices =(
("1", "One"),
("2", "Two"),
("3", "Three"),
)
class Appointment(models.Model):
id = models.AutoField(primary_key=True)
fullName = models.CharField(max_length=100)
gender = models.CharField(max_length=300, choices=genderChoices)
email = models.CharField(max_length=255)
doctorName = models.CharField(max_length=255)
appointmentTime =models.DateTimeField()
class specificAppointment(models.Model):
email = models.CharField(max_length=100)
class File(models.Model):
file = models.FileField(blank=False, null=False)
def __str__(self):
return self.file.name
\ No newline at end of file
import easyocr
import cv2
from matplotlib import pyplot as plt
import numpy as np
def main(file):
IMAGE_PATH = file
reader = easyocr.Reader(['en'])
result = reader.readtext(IMAGE_PATH)
# print(result)
image_values = []
for x in result:
# print(x[1])
image_values.append(x[1])
final_result = []
medicines = []
final_result.append(('Date', str(image_values[4].replace('Date:', ''))))
final_result.append(('Name', str(image_values[7].replace('Your Name:', ''))))
final_result.append(('Address', str(image_values[8].replace('Address:', ''))))
final_result.append(('Medicines', image_values[9:]))
# out final result
for f in final_result:
print(f)
img = cv2.imread(IMAGE_PATH)
font = cv2.FONT_HERSHEY_SIMPLEX
# Date
top_left = tuple(result[4][0][0])
bottom_right = tuple(result[4][0][2])
date_text = result[4][1]
img = cv2.rectangle(img, top_left, bottom_right, (0, 255, 0), 5)
img = cv2.putText(img, date_text, top_left, font, 0.5, (0, 0, 0), 3, cv2.LINE_AA)
# Name
top_left = tuple(result[7][0][0])
bottom_right = tuple(result[7][0][2])
text = result[7][1]
font = cv2.FONT_HERSHEY_SIMPLEX
img = cv2.rectangle(img, top_left, bottom_right, (0, 255, 0), 5)
img = cv2.putText(img, text, top_left, font, 0.5, (0, 0, 0), 3, cv2.LINE_AA)
# Address
top_left = tuple(result[8][0][0])
bottom_right = tuple(result[8][0][2])
text = result[8][1]
font = cv2.FONT_HERSHEY_SIMPLEX
img = cv2.rectangle(img, top_left, bottom_right, (0, 255, 0), 5)
img = cv2.putText(img, text, top_left, font, 0.5, (0, 0, 0), 3, cv2.LINE_AA)
# Medicine
for i in range(9, len(result)-1):
top_left = tuple(result[i][0][0])
bottom_right = tuple(result[i][0][2])
text = result[i][1]
font = cv2.FONT_HERSHEY_SIMPLEX
img = cv2.rectangle(img, top_left, bottom_right, (0, 255, 0), 5)
img = cv2.putText(img, text, top_left, font, 0.5, (0, 0, 0), 3, cv2.LINE_AA)
return final_result
# main('new/3.jpeg')
# plt.imshow(img)
# plt.show()
from rest_framework.serializers import ModelSerializer
from .models import User,Appointment, specificAppointment
from .models import File
class UserSerializer(ModelSerializer):
class Meta:
model = User
fields = ['id', 'name', 'email', 'password']
extra_kwargs = {
'password': {'write_only': True}
}
def create(self, validated_data):
password = validated_data.pop('password', None)
instance = self.Meta.model(**validated_data)
if password is not None:
instance.set_password(password)
instance.save()
return instance
class AppointmentSerializer(ModelSerializer):
class Meta:
model = Appointment
fields = ['id', 'fullName', 'gender', 'email', 'doctorName','appointmentTime']
class SpecificAppointmentSerilaizer(ModelSerializer):
class Meta:
model = specificAppointment
fields = "__all__"
class FileSerializer(ModelSerializer):
class Meta:
model = File
fields = "__all__"
from django.test import TestCase
# Create your tests here.
from django.urls import path
from .views import RegisterAPIView, LoginAPIView, UserAPIView, RefreshAPIView, LogoutAPIView, AppointmentAPIView, FileUploadView, SpecificAppointmentAPIView
urlpatterns = [
path('register', RegisterAPIView.as_view()),
path('login', LoginAPIView.as_view()),
path('user', UserAPIView.as_view()),
path('refresh', RefreshAPIView.as_view()),
path('logout', LogoutAPIView.as_view()),
path('appointment', AppointmentAPIView.as_view()),
path('medicine', FileUploadView.as_view()),
path('specificAppointment', SpecificAppointmentAPIView.as_view())
]
from rest_framework.authentication import get_authorization_header
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.exceptions import APIException, AuthenticationFailed
from rest_framework import status
from rest_framework.parsers import FileUploadParser
from .authentication import create_access_token, create_refresh_token, decode_access_token, decode_refresh_token
from .serializers import UserSerializer,AppointmentSerializer, SpecificAppointmentSerilaizer
from .models import User,Appointment, specificAppointment
from .serializers import FileSerializer
from .predict import main
class RegisterAPIView(APIView):
def post(self, request):
serializer = UserSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data)
class LoginAPIView(APIView):
def post(self, request):
user = User.objects.filter(email=request.data['email']).first()
if not user:
raise APIException('Invalid credentials!')
if not user.check_password(request.data['password']):
raise APIException('Invalid credentials!')
access_token = create_access_token(user.id)
refresh_token = create_refresh_token(user.id)
response = Response()
response.set_cookie(key='refreshToken', value=refresh_token, httponly=True)
response.data = {
'token': access_token
}
return response
class UserAPIView(APIView):
def get(self, request):
auth = get_authorization_header(request).split()
if auth and len(auth) == 2:
token = auth[1].decode('utf-8')
id = decode_access_token(token)
user = User.objects.filter(pk=id).first()
return Response(UserSerializer(user).data)
raise AuthenticationFailed('unauthenticated')
class RefreshAPIView(APIView):
def post(self, request):
refresh_token = request.COOKIES.get('refreshToken')
id = decode_refresh_token(refresh_token)
access_token = create_access_token(id)
return Response({
'token': access_token
})
class LogoutAPIView(APIView):
def post(self, _):
response = Response()
response.delete_cookie(key="refreshToken")
response.data = {
'message': 'success'
}
return response
class AppointmentAPIView(APIView):
def post(self,request):
serializer = AppointmentSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data)
def checkAppointment(email,arrayValue):
a = []
for x in range(len(arrayValue)):
# print(arrayValue[0]['email'])
if email == arrayValue[x]['doctorName']:
a.append(arrayValue[x])
return a
class SpecificAppointmentAPIView(APIView):
def post(self, request, *args, **kwargs):
serializer = SpecificAppointmentSerilaizer(data=request.data)
serializer.is_valid(raise_exception=True)
snippets = Appointment.objects.all()
serializer_1 = AppointmentSerializer(snippets, many=True)
value = checkAppointment(serializer.data['email'], serializer_1.data)
return Response(value)
class FileUploadView(APIView):
parser_class = (FileUploadParser,)
def post(self, request, *args, **kwargs):
file_serializer = FileSerializer(data=request.data)
if file_serializer.is_valid():
file_serializer.save()
result=file_serializer.data
result_class = main(result['file'][1:])
return Response(result_class, status=status.HTTP_201_CREATED)
else:
return Response(file_serializer.errors, status=status.HTTP_400_BAD_REQUEST)
\ No newline at end of file
#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys
def main():
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'app.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)
if __name__ == '__main__':
main()
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment