diff options
Diffstat (limited to 'workshop_app')
55 files changed, 3286 insertions, 0 deletions
diff --git a/workshop_app/__init__.py b/workshop_app/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/workshop_app/__init__.py diff --git a/workshop_app/admin.py b/workshop_app/admin.py new file mode 100644 index 0000000..2f8017a --- /dev/null +++ b/workshop_app/admin.py @@ -0,0 +1,12 @@ +from django.contrib import admin +from .models import ( + Profile, WorkshopType, + Workshop, ProposeWorkshopDate, + RequestedWorkshop) + +# Register your models here. +admin.site.register(Profile) +admin.site.register(WorkshopType) +admin.site.register(Workshop) +admin.site.register(ProposeWorkshopDate) +admin.site.register(RequestedWorkshop) diff --git a/workshop_app/apps.py b/workshop_app/apps.py new file mode 100644 index 0000000..dc9a567 --- /dev/null +++ b/workshop_app/apps.py @@ -0,0 +1,7 @@ +from __future__ import unicode_literals + +from django.apps import AppConfig + + +class WorkshopAppConfig(AppConfig): + name = 'workshop_app' diff --git a/workshop_app/data/instructions-for-coordinators.pdf b/workshop_app/data/instructions-for-coordinators.pdf Binary files differnew file mode 100755 index 0000000..7601616 --- /dev/null +++ b/workshop_app/data/instructions-for-coordinators.pdf diff --git a/workshop_app/data/instructions-for-participants.pdf b/workshop_app/data/instructions-for-participants.pdf Binary files differnew file mode 100755 index 0000000..93a3e5d --- /dev/null +++ b/workshop_app/data/instructions-for-participants.pdf diff --git a/workshop_app/data/schedule.pdf b/workshop_app/data/schedule.pdf Binary files differnew file mode 100755 index 0000000..203f5e0 --- /dev/null +++ b/workshop_app/data/schedule.pdf diff --git a/workshop_app/forms.py b/workshop_app/forms.py new file mode 100644 index 0000000..3ee457a --- /dev/null +++ b/workshop_app/forms.py @@ -0,0 +1,186 @@ +from django import forms +from django.utils import timezone +from .models import ( + Profile, User, Workshop, WorkshopType, + RequestedWorkshop, BookedWorkshop, ProposeWorkshopDate + ) +from string import punctuation, digits +try: + from string import letters +except ImportError: + from string import ascii_letters as letters + +from django.contrib.auth.models import User +from django.contrib.auth import authenticate +from .send_mails import generate_activation_key + + +UNAME_CHARS = letters + "._" + digits +PWD_CHARS = letters + punctuation + digits + +position_choices = ( + ("coordinator", "Coordinator"), + ("instructor", "Instructor") + ) + +class UserRegistrationForm(forms.Form): + """A Class to create new form for User's Registration. + It has the various fields and functions required to register + a new user to the system""" + required_css_class = 'required' + username = forms.CharField(max_length=32, help_text='''Letters, digits, + period only.''') + email = forms.EmailField() + password = forms.CharField(max_length=32, widget=forms.PasswordInput()) + confirm_password = forms.CharField\ + (max_length=32, widget=forms.PasswordInput()) + first_name = forms.CharField(max_length=32) + last_name = forms.CharField(max_length=32) + phone_number = forms.RegexField(regex=r'^\+?1?\d{9,15}$', + error_message=("Phone number must be entered \ + in the format: '+999999999'.\ + Up to 15 digits allowed.")) + institute = forms.CharField(max_length=128, + help_text='Institute/Organization') + department = forms.CharField(max_length=64, help_text='Department you work/\ + study') + position = forms.ChoiceField(help_text='Instructors, please wait \ + for our admin approval, if your instructor \ + account is not activated in 7 days, please\ + mail us at workshops[at]fossee[dot]in', + choices=position_choices + ) + + def clean_username(self): + u_name = self.cleaned_data["username"] + if u_name.strip(UNAME_CHARS): + msg = "Only letters, digits, period are"\ + " allowed in username" + raise forms.ValidationError(msg) + try: + User.objects.get(username__exact=u_name) + raise forms.ValidationError("Username already exists.") + except User.DoesNotExist: + return u_name + + def clean_password(self): + pwd = self.cleaned_data['password'] + if pwd.strip(PWD_CHARS): + raise forms.ValidationError("Only letters, digits and punctuation\ + are allowed in password") + return pwd + + def clean_confirm_password(self): + c_pwd = self.cleaned_data['confirm_password'] + pwd = self.data['password'] + if c_pwd != pwd: + raise forms.ValidationError("Passwords do not match") + + return c_pwd + + # def clean_email(self): + # user_email = self.cleaned_data['email'] + # if User.objects.filter(email=user_email).exists(): + # raise forms.ValidationError("This email already exists") + # return user_email + + def save(self): + u_name = self.cleaned_data["username"] + u_name = u_name.lower() + pwd = self.cleaned_data["password"] + email = self.cleaned_data["email"] + new_user = User.objects.create_user(u_name, email, pwd) + new_user.first_name = self.cleaned_data["first_name"] + new_user.last_name = self.cleaned_data["last_name"] + new_user.save() + + cleaned_data = self.cleaned_data + new_profile = Profile(user=new_user) + new_profile.institute = cleaned_data["institute"] + new_profile.department = cleaned_data["department"] + new_profile.position = cleaned_data["position"] + new_profile.phone_number = cleaned_data["phone_number"] + new_profile.activation_key = generate_activation_key(new_user.username) + new_profile.key_expiry_time = timezone.now() + \ + timezone.timedelta(days=3) + new_profile.save() + key = Profile.objects.get(user=new_user).activation_key + return u_name, pwd, key + +class UserLoginForm(forms.Form): + """Creates a form which will allow the user to log into the system.""" + + username = forms.CharField(max_length=32) + password = forms.CharField(max_length=32, widget=forms.PasswordInput()) + + def clean(self): + super(UserLoginForm, self).clean() + try: + u_name, pwd = self.cleaned_data["username"],\ + self.cleaned_data["password"] + user = authenticate(username=u_name, password=pwd) + except Exception: + raise forms.ValidationError\ + ("Username and/or Password is not entered") + if not user: + raise forms.ValidationError("Invalid username/password") + return user + +class ProfileForm(forms.ModelForm): + """ profile form for coordinator and instructor """ + + class Meta: + model = Profile + fields = ['first_name', 'last_name', 'institute', 'department', + ] + + first_name = forms.CharField(max_length=32) + last_name = forms.CharField(max_length=32) + + def __init__(self, *args, **kwargs): + if 'user' in kwargs: + user = kwargs.pop('user') + super(ProfileForm, self).__init__(*args, **kwargs) + self.fields['first_name'].initial = user.first_name + self.fields['last_name'].initial = user.last_name + +class CreateWorkshop(forms.ModelForm): + """ + Instructors can create Workshops based on the Types + of available workshops. + """ + + def __init__( self, *args, **kwargs ): + kwargs.setdefault('label_suffix', '') + super(CreateWorkshop, self).__init__( *args, **kwargs ) + self.fields['recurrences'].label = " " #the trick to hide field :) + + class Meta: + model = Workshop + fields = ['workshop_title', 'recurrences'] + + +class ProposeWorkshopDateForm(forms.ModelForm): + """ + Coordinators will propose a workshop and date + """ + + def __init__( self, *args, **kwargs ): + kwargs.setdefault('label_suffix', '') + super(ProposeWorkshopDateForm, self).__init__(*args, **kwargs) + self.fields['condition_one'].label = "" + self.fields['condition_one'].required = True + self.fields['condition_two'].label = "" + self.fields['condition_two'].required = True + self.fields['condition_three'].label = "" + self.fields['condition_three'].required = True + + class Meta: + model = ProposeWorkshopDate + fields = ['condition_one','condition_two','condition_three', + 'proposed_workshop_title', 'proposed_workshop_date'] + widgets = { + 'proposed_workshop_date': forms.DateInput(attrs={ + 'class':'datepicker'}), + } + diff --git a/workshop_app/migrations/__init__.py b/workshop_app/migrations/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/workshop_app/migrations/__init__.py diff --git a/workshop_app/models.py b/workshop_app/models.py new file mode 100644 index 0000000..8eae29e --- /dev/null +++ b/workshop_app/models.py @@ -0,0 +1,142 @@ + +from django.db import models +from django.contrib.auth.models import User +from django.core.validators import RegexValidator +from recurrence.fields import RecurrenceField + +position_choices = ( + ("coordinator", "Coordinator"), + ("instructor", "Instructor") + ) + + +def has_profile(user): + """ check if user has profile """ + return True if hasattr(user, 'profile') else False + +class Profile(models.Model): + """Profile for users(instructors and coordinators)""" + + user = models.OneToOneField(User) + institute = models.CharField(max_length=150) + department = models.CharField(max_length=150) + phone_number = models.CharField( + max_length=15, + validators=[RegexValidator( + regex=r'^\+?1?\d{9,15}$', message=( + "Phone number must be entered \ + in the format: '+929490956'.\ + Up to 15 digits allowed.") + )]) + position = models.CharField(max_length=32, choices=position_choices) + is_email_verified = models.BooleanField(default=False) + activation_key = models.CharField(max_length=255, blank=True, null=True) + key_expiry_time = models.DateTimeField(blank=True, null=True) + + def __str__(self): + return u"id: {0}| {1} {2} | {3} ".format( + self.user.id, + self.user.first_name, + self.user.last_name, + self.user.email + ) + + +class WorkshopType(models.Model): + """"Admin creates types of workshops which can be used by the instructor + to create workshops. + """ + + workshoptype_name = models.CharField(max_length=120) + workshoptype_description = models.TextField() + workshoptype_duration = models.CharField(max_length=32, + help_text='Please write this in \ + following format eg: 3days, 8hours a day') + + def __str__(self): + return u"{0} {1}".format(self.workshoptype_name, + self.workshoptype_duration + ) + + +class Workshop(models.Model): + """Instructor Creates workshop based on + WorkshopTypes available""" + + workshop_instructor = models.ForeignKey(User, on_delete=models.CASCADE) + workshop_title = models.ForeignKey( + WorkshopType, on_delete=models.CASCADE, + help_text=' [Select the type of workshop.] ' + ) + #For recurring workshops source: django-recurrence + recurrences = RecurrenceField() + + def __str__(self): + return u"{0} | {1} ".format( + self.workshop_title, + self.workshop_instructor + ) + + +class RequestedWorkshop(models.Model): + """ + Contains Data of request for Workshops + """ + + requested_workshop_instructor = models.ForeignKey( + User, + on_delete=models.CASCADE + ) + requested_workshop_coordinator = models.ForeignKey( + User, + related_name="%(app_label)s_%(class)s_related" + ) + requested_workshop_date = models.DateField() + status = models.CharField( + max_length=32, default="Pending" + ) + requested_workshop_title = models.ForeignKey( + WorkshopType, + on_delete=models.CASCADE + ) + + +class ProposeWorkshopDate(models.Model): + """ + Contains details of proposed date and workshop from coordinator + """ + + condition_one = models.BooleanField(default=False, help_text='I will give\ + minimum 50 participants for the workshop.') + condition_two = models.BooleanField(default=False, help_text='I agree \ + that this booking won\'t be cancelled without \ + prior notice to the instructor and fossee.') + condition_three = models.BooleanField(default=False, help_text='This \ + proposal is subject to FOSSEE and instructor approval.') + + proposed_workshop_coordinator = models.ForeignKey( + User, + on_delete=models.CASCADE + ) + proposed_workshop_instructor = models.ForeignKey(User, null=True, + related_name="%(app_label)s_%(class)s_related") + + proposed_workshop_title = models.ForeignKey( + WorkshopType, on_delete=models.CASCADE, + help_text='Select the type of workshop.' + ) + + proposed_workshop_date = models.DateField() + + status = models.CharField( + max_length=32, default="Pending" + ) + + +class BookedWorkshop(models.Model): + """ + Contains details about Confirmed Booked/Completed Workshops + """ + + booked_workshop_requested = models.ForeignKey(RequestedWorkshop, null=True) + booked_workshop_proposed = models.ForeignKey(ProposeWorkshopDate, null=True) diff --git a/workshop_app/send_mails.py b/workshop_app/send_mails.py new file mode 100644 index 0000000..a8ada76 --- /dev/null +++ b/workshop_app/send_mails.py @@ -0,0 +1,334 @@ +__author__ = "Akshen Doke" + +from django.core.mail import send_mail +from textwrap import dedent +from random import randint +import hashlib +from django.utils.crypto import get_random_string +from string import punctuation, digits +try: + from string import letters +except ImportError: + from string import ascii_letters as letters +from workshop_portal.settings import ( + EMAIL_HOST, + EMAIL_PORT, + EMAIL_HOST_USER, + EMAIL_HOST_PASSWORD, + EMAIL_USE_TLS, + PRODUCTION_URL + ) + +def generate_activation_key(username): + """Generates hashed secret key for email activation""" + chars = letters + digits + punctuation + secret_key = get_random_string(randint(10,40), chars) + return hashlib.sha256((secret_key + username).encode('utf-8')).hexdigest() + +def send_smtp_email(request=None, subject=None, message=None, + user_position=None, workshop_date=None, + workshop_title=None, user_name=None, + other_email=None, phone_number=None, + institute=None, attachment=None): + ''' + Send email using SMTPLIB + ''' + + from smtplib import SMTP + from email.mime.multipart import MIMEMultipart + from email.mime.text import MIMEText + from email.mime.base import MIMEBase + from email import encoders + + msg = MIMEMultipart() + msg['From'] = EMAIL_HOST_USER + msg['To'] = other_email + msg['Subject'] = subject + body = message + msg.attach(MIMEText(body, 'plain')) + + if attachment: + from django.conf import settings + from os import listdir, path + files = listdir(settings.MEDIA_ROOT) + for f in files: + print(path.join(settings.MEDIA_ROOT,f)) + attachment = open(path.join(settings.MEDIA_ROOT,f), 'rb') + part = MIMEBase('application', 'octet-stream') + part.set_payload((attachment).read()) + encoders.encode_base64(part) + part.add_header('Content-Disposition', "attachment; filename= %s " % f) + msg.attach(part) + + + server = SMTP(EMAIL_HOST, EMAIL_PORT) + server.ehlo() + server.starttls() + server.ehlo() + server.esmtp_features['auth']='LOGIN DIGEST-MD5 PLAIN' + server.login(EMAIL_HOST_USER, EMAIL_HOST_PASSWORD) + text = msg.as_string() + server.sendmail(EMAIL_HOST_USER, other_email, text) + server.close() + + +def send_email( request, call_on, + user_position=None, workshop_date=None, + workshop_title=None, user_name=None, + other_email=None, phone_number=None, + institute=None, key=None + ): + ''' + Email sending function while registration and + booking confirmation. + ''' + + if call_on == "Registration": + if user_position == "instructor": + message = dedent("""\ + Your request as an Instructor at FOSSEE, IIT Bombay + has been received. Please click on the below link to + activate your account + {0}/activate_user/{1} + + You will be notified via email on + approval of your instructor account + within 3 working days. + + In case of queries regarding the same revert to this + email.""".format(PRODUCTION_URL, key)) + + try: + send_mail( + "Instructor Registration - FOSSEE, IIT Bombay", message, + EMAIL_HOST_USER, [request.user.email], fail_silently=False + ) + except Exception: + send_smtp_email(request=request, + subject="Instructor Registration - FOSSEE, IIT Bombay", + message=message, other_email=request.user.email, + ) + + + #Send a mail to admin as well. + message = dedent("""\ + A new instructor request has been received. + + Instructor name: {0} + Instructor email: {1} + + Please verify the profile and mail the user within 2 + working days.""".format(request.user, request.user.email)) + + try: + send_mail("New Instructor Registration - FOSSEE, IIT Bombay", + message, EMAIL_HOST_USER, ['workshops@fossee.in'], + fail_silently=False) + except Exception: + send_smtp_email(request=request, + subject="Instructor Registration - FOSSEE, IIT Bombay", + message=message, other_email='workshops@fossee.in', + ) + + else: + message = dedent("""\ + Thank you for registering as a coordinator with us. + + Your request as a coordinator has been accepted. + Please click on the below link to + activate your account + {0}/activate_user/{1} + + After activation you can proceed to book your dates for + the workshop(s). + + In case of queries regarding workshop booking(s), + revert to this email.""".format(PRODUCTION_URL, key)) + + try: + send_mail( + "Coordinator Registration at FOSSEE, IIT Bombay", message, EMAIL_HOST_USER, + [request.user.email], fail_silently=False + ) + except Exception: + send_smtp_email(request=request, + subject="Coordinator Registration - FOSSEE, IIT Bombay", + message=message, other_email=request.user.email, + ) + + elif call_on == "Booking": + if user_position == "instructor": + message = dedent("""\ + Coordinator name:{0} + Coordinator email: {1} + Contact number:{2} + Institute:{3} + Workshop date:{4} + Workshop title:{5} + + You may accept or reject this booking + workshop.fossee.in .""".format( + user_name, request.user.email, + request.user.profile.phone_number, + request.user.profile.institute, + workshop_date, workshop_title + )) + + try: + send_mail( + "New FOSSEE Workshop booking on {0}".format(workshop_date), + message, EMAIL_HOST_USER, [other_email], + fail_silently=False + ) + except Exception: + send_smtp_email(request=request, + subject="New FOSSEE Workshop booking on {0}" + .format(workshop_date), + message=message, other_email=other_email, + ) + else: + message = dedent("""\ + Thank You for New FOSSEE Workshop booking. + + Workshop date:{0} + Workshop title:{1} + + Your request has been received and is awaiting instructor + approval/disapproval. You will be notified about the status + via email and on your workshops.fossee.in + + In case of queries regarding workshop booking(s), revert + to this email.""".format( + workshop_date, workshop_title + )) + + try: + send_mail( + "Pending Request for New FOSSEE Workshop booking on {0}" + .format(workshop_date), message, EMAIL_HOST_USER, + [request.user.email], fail_silently=False + ) + except Exception: + send_smtp_email(request=request, + subject="Pending Request for New FOSSEE Workshop booking \ + on {0}".format(workshop_date), + message=message, other_email=request.user.email, + ) + + elif call_on == "Booking Confirmed": + if user_position == "instructor": + message = dedent("""\ + Coordinator name:{0} + Coordinator email: {1} + Contact number:{2} + Institute:{3} + Workshop date:{4} + Workshop title:{5} + + You have accepted this booking. Detailed instructions have + been sent to the coordinator. """.format(user_name, other_email, + phone_number, institute, workshop_date, workshop_title)) + + send_smtp_email(request=request, + subject="FOSSEE Workshop booking confirmation on {0}". + format(workshop_date), message=message, + other_email=request.user.email, attachment=1 + ) + else: + message = dedent("""\ + Instructor name:{0} + Instructor email: {1} + Contact number:{2} + Workshop date:{3} + Workshop title:{4} + + Your workshop booking has been accepted. Detailed + instructions are attached below. + + In case of queries regarding the workshop + instructions/schedule revert to this email.""".format( + request.user.username, request.user.email, + phone_number, workshop_date, workshop_title + )) + + send_smtp_email(request=request, + subject="FOSSEE Workshop booking confirmation on {0}". + format(workshop_date), message=message, + other_email=other_email, attachment=1 + ) + + elif call_on == "Booking Request Rejected": + if user_position == "instructor": + message = dedent("""\ + Coordinator name:{0} + Coordinator email: {1} + Contact number:{2} + Institute:{3} + Workshop date:{4} + Workshop title:{4} + + You have rejected this booking. The coordinator has + been notified.""".format(user_name, other_email, + phone_number, institute, + workshop_date, workshop_title)) + + try: + send_mail("FOSSEE Workshop booking rejected for {0}" + .format(workshop_date), message, EMAIL_HOST_USER, + [request.user.email], fail_silently=False) + except Exception: + send_smtp_email(request=request, + subject="FOSSEE Workshop booking rejected for {0}". + format(workshop_date), message=message, + other_email=request.user.email + ) + else: + message = dedent("""\ + Workshop date:{0} + Workshop title:{1} + + We regret to inform you that your workshop booking + has been rejected due to unavailability of the + instructor. You may try booking other available + slots workshops.fossee.in """ + .format(workshop_date, workshop_title)) + + try: + send_mail("FOSSEE Workshop booking rejected for {0}". + format(workshop_date), message, EMAIL_HOST_USER, + [other_email], fail_silently=False) + except Exception: + send_smtp_email(request=request, + subject="FOSSEE Workshop booking rejected for {0}". + format(workshop_date), message=message, + other_email=other_email + ) + + elif call_on =='Workshop Deleted': + message = dedent("""\ + You have deleted a Workshop. + + Workshop date:{0} + Workshop title:{1}""" + .format(workshop_date, workshop_title)) + try: + send_mail("FOSSEE workshop deleted for {0}".format(workshop_date), + message, EMAIL_HOST_USER, [request.user.email], + fail_silently=False) + except Exception: + send_smtp_email(request=request, + subject="FOSSEE Workshop deleted for {0}". + format(workshop_date), message=message, + other_email=request.user.email + ) + + else: + message = "Issue at Workshop Booking App please check" + try: + send_mail("Issue At Workshop Booking App Mailing", message, EMAIL_HOST_USER, + ['doke.akshen@gmail.com', 'mahesh.p.gudi@gmail.com', 'aditya94palaparthy@gmail.com'], fail_silently=False) + except Exception: + send_smtp_email(request=request, + subject="Issue at Workshop Booking App please check", + message=message, other_email='doke.akshen@gmail.com' + ) diff --git a/workshop_app/static/workshop_app/css/faq.css b/workshop_app/static/workshop_app/css/faq.css new file mode 100644 index 0000000..98b4f5c --- /dev/null +++ b/workshop_app/static/workshop_app/css/faq.css @@ -0,0 +1,5 @@ +.num { + list-style-type: square; + font-family: 'Antic Slab'; + font-size: 22px; +} diff --git a/workshop_app/static/workshop_app/css/index.css b/workshop_app/static/workshop_app/css/index.css new file mode 100644 index 0000000..1087d24 --- /dev/null +++ b/workshop_app/static/workshop_app/css/index.css @@ -0,0 +1,104 @@ + +body { + background-color: grey; +} + +.fossee-label { + padding-top: 20%; + margin-left: 9%; + color: #6D5847; + font-size: 400%; +} + +.logo { + float: left; + margin-top: 9%; + margin-left: 15%; +} + +.label-bar { + color: #6D5847; + float: right; + margin-top: 9%; + font-size: 120%; + margin-right: 3%; +} + + +.login { + margin-left: auto; + margin-right: 1%; + width: 40%; + height: 90%; + background: white; +} + +#rectbox { + border-radius: 9%; + background: #6D5847; + padding: 3%; + margin-left: 10%; + margin-top: 3%; + width: 75%; + height: 60%; +} + + + +/* Icons with their respective Images */ +.icons { + background: white; + margin-top: 3%; +} + +figure.item { + /* To correctly align image, regardless of content height: */ + vertical-align: top; + display: inline-block; + /* To horizontally center images and caption */ + text-align: center; + /* The width of the container also implies margin around the images. */ +} + + + + + +/* Contact Us, Related Links and Organization Logo css*/ + + +.org-logo { + margin-top: 1%; + + float: left; + color: #5A3700; + +} + +.related-links { + font-size: 120%; + color: #5A3700; + text-align: center; + margin-top: 1%; +} + +.contact-us { + font-size: 140%; + color: #5A3700; + margin-top: 1%; + + float: right; + +} + +/* Footer */ +.footer { + position: relative; + right: 0; + bottom: 0; + left: 0; + + background-color: black; + text-align: center; + color:white; +} diff --git a/workshop_app/static/workshop_app/css/modal.css b/workshop_app/static/workshop_app/css/modal.css new file mode 100644 index 0000000..dc767a0 --- /dev/null +++ b/workshop_app/static/workshop_app/css/modal.css @@ -0,0 +1,20 @@ +#overlay { + visibility: hidden; + position: absolute; + left: 0px; + top: 0px; + width:100%; + height:100%; + text-align:center; + z-index: 1000; +} + +#overlay div { + width:900px; + height: 450px; + margin: 100px auto; + background-color: #fff; + border:1px solid #000; + padding:15px; + text-align:center; +} diff --git a/workshop_app/static/workshop_app/css/sticky-footer.css b/workshop_app/static/workshop_app/css/sticky-footer.css new file mode 100644 index 0000000..cb21144 --- /dev/null +++ b/workshop_app/static/workshop_app/css/sticky-footer.css @@ -0,0 +1,44 @@ +/* Navbar */ +.navbar-custom { + background-color:#6D5847; + color:black; + border-radius:0; +} + +/* Text color */ +.navbar-custom .navbar-nav > li > a { + color:#fff; +} + +/* OnActive Tab */ +.navbar-custom .navbar-nav > .active > a { + color: black; + background: white; +} + +.navbar-custom .navbar-nav > li > a:hover, +.navbar-custom .navbar-nav > li > a:focus, +.navbar-custom .navbar-nav > .active > a:hover, +.navbar-custom .navbar-nav > .active > a:focus, +.navbar-custom .navbar-nav > .open >a { + text-decoration: none; + background-color: #fff; +} + +/* Brand-CompanyName */ +.navbar-custom .navbar-brand { + color:#efefef; + background-color: black; +} + +/* Footer CSS */ +.footer { + position: relative; + bottom: 0; + right: 0; + left: 0; +} + +.hiddenRow { + padding: 0 !important; +}
\ No newline at end of file diff --git a/workshop_app/static/workshop_app/img/Dwsim_logo.png b/workshop_app/static/workshop_app/img/Dwsim_logo.png Binary files differnew file mode 100644 index 0000000..1b22085 --- /dev/null +++ b/workshop_app/static/workshop_app/img/Dwsim_logo.png diff --git a/workshop_app/static/workshop_app/img/OR_logo.png b/workshop_app/static/workshop_app/img/OR_logo.png Binary files differnew file mode 100644 index 0000000..88bd685 --- /dev/null +++ b/workshop_app/static/workshop_app/img/OR_logo.png diff --git a/workshop_app/static/workshop_app/img/OpenFoam_logo.png b/workshop_app/static/workshop_app/img/OpenFoam_logo.png Binary files differnew file mode 100644 index 0000000..5e674ed --- /dev/null +++ b/workshop_app/static/workshop_app/img/OpenFoam_logo.png diff --git a/workshop_app/static/workshop_app/img/Scilab_logo.png b/workshop_app/static/workshop_app/img/Scilab_logo.png Binary files differnew file mode 100644 index 0000000..f2babe2 --- /dev/null +++ b/workshop_app/static/workshop_app/img/Scilab_logo.png diff --git a/workshop_app/static/workshop_app/img/bnft.png b/workshop_app/static/workshop_app/img/bnft.png Binary files differnew file mode 100644 index 0000000..4b26613 --- /dev/null +++ b/workshop_app/static/workshop_app/img/bnft.png diff --git a/workshop_app/static/workshop_app/img/cc.png b/workshop_app/static/workshop_app/img/cc.png Binary files differnew file mode 100644 index 0000000..72c7cf6 --- /dev/null +++ b/workshop_app/static/workshop_app/img/cc.png diff --git a/workshop_app/static/workshop_app/img/esim_logo.png b/workshop_app/static/workshop_app/img/esim_logo.png Binary files differnew file mode 100644 index 0000000..ea73365 --- /dev/null +++ b/workshop_app/static/workshop_app/img/esim_logo.png diff --git a/workshop_app/static/workshop_app/img/faq.png b/workshop_app/static/workshop_app/img/faq.png Binary files differnew file mode 100644 index 0000000..e2caf34 --- /dev/null +++ b/workshop_app/static/workshop_app/img/faq.png diff --git a/workshop_app/static/workshop_app/img/fossee_logo.png b/workshop_app/static/workshop_app/img/fossee_logo.png Binary files differnew file mode 100644 index 0000000..d2d18d0 --- /dev/null +++ b/workshop_app/static/workshop_app/img/fossee_logo.png diff --git a/workshop_app/static/workshop_app/img/homepg.png b/workshop_app/static/workshop_app/img/homepg.png Binary files differnew file mode 100644 index 0000000..4943deb --- /dev/null +++ b/workshop_app/static/workshop_app/img/homepg.png diff --git a/workshop_app/static/workshop_app/img/iitb_logo.png b/workshop_app/static/workshop_app/img/iitb_logo.png Binary files differnew file mode 100644 index 0000000..70b2c46 --- /dev/null +++ b/workshop_app/static/workshop_app/img/iitb_logo.png diff --git a/workshop_app/static/workshop_app/img/img1.png b/workshop_app/static/workshop_app/img/img1.png Binary files differnew file mode 100644 index 0000000..07dc07f --- /dev/null +++ b/workshop_app/static/workshop_app/img/img1.png diff --git a/workshop_app/static/workshop_app/img/img2.jpg b/workshop_app/static/workshop_app/img/img2.jpg Binary files differnew file mode 100644 index 0000000..fd18675 --- /dev/null +++ b/workshop_app/static/workshop_app/img/img2.jpg diff --git a/workshop_app/static/workshop_app/img/img_1.png b/workshop_app/static/workshop_app/img/img_1.png Binary files differnew file mode 100644 index 0000000..3824f16 --- /dev/null +++ b/workshop_app/static/workshop_app/img/img_1.png diff --git a/workshop_app/static/workshop_app/img/list.png b/workshop_app/static/workshop_app/img/list.png Binary files differnew file mode 100644 index 0000000..6eb0640 --- /dev/null +++ b/workshop_app/static/workshop_app/img/list.png diff --git a/workshop_app/static/workshop_app/img/part.png b/workshop_app/static/workshop_app/img/part.png Binary files differnew file mode 100644 index 0000000..915e6c9 --- /dev/null +++ b/workshop_app/static/workshop_app/img/part.png diff --git a/workshop_app/static/workshop_app/img/python_logo.png b/workshop_app/static/workshop_app/img/python_logo.png Binary files differnew file mode 100644 index 0000000..c147919 --- /dev/null +++ b/workshop_app/static/workshop_app/img/python_logo.png diff --git a/workshop_app/static/workshop_app/img/sandhi_logo.png b/workshop_app/static/workshop_app/img/sandhi_logo.png Binary files differnew file mode 100644 index 0000000..1c35e0e --- /dev/null +++ b/workshop_app/static/workshop_app/img/sandhi_logo.png diff --git a/workshop_app/static/workshop_app/js/overlay.js b/workshop_app/static/workshop_app/js/overlay.js new file mode 100644 index 0000000..b4165c4 --- /dev/null +++ b/workshop_app/static/workshop_app/js/overlay.js @@ -0,0 +1,7 @@ +// function overlay(course_no) { +// el = document.getElementById("overlay"); +// course_id = document.getElementById("course_id"); +// el.style.visibility = (el.style.visibility == "visible") ? "hidden" : "visible"; + +// console.log(course_no); +// }
\ No newline at end of file diff --git a/workshop_app/templates/workshop_app/activation.html b/workshop_app/templates/workshop_app/activation.html new file mode 100644 index 0000000..1262e22 --- /dev/null +++ b/workshop_app/templates/workshop_app/activation.html @@ -0,0 +1,39 @@ +{% extends 'workshop_app/base.html' %} + +{% block title %} + Awating activation +{% endblock %} + +{% block header %} + <nav class="navbar navbar-default navbar-custom"> + <div class="container-fluid"> + <div class="navbar-header"> + <a class="navbar-brand" href="#">SiteName</a> + </div> + <ul class="nav navbar-nav navbar-right"> + {% if request.user.profile.is_email_verified %} + <li><a href="{{ URL_ROOT }}/view_profile/"><span class="glyphicon glyphicon-user"></span> Profile</a></li> + {% endif %} + <li><a href="{{ URL_ROOT }}/logout/"><span class="glyphicon glyphicon-log-out"></span> Logout</a></li> + </ul> + </div> + </nav> +{% endblock %} + +{% block content %} + {% if status %} + <div class="container"> + <div class="jumbotron"> + <p>{{ status }}</p> + {{ request.user.profile.activation_key }} + </div> + </div> + {% else %} + <div class="container"> + <div class="jumbotron"> + <h1>Activation Awaiting</h1> + <p>Please <strong>Logout</strong> and check your email to activate your account. The key expires in <strong>3days</strong> from the date of registeration</p> + </div> + </div> + {% endif %} +{% endblock %}
\ No newline at end of file diff --git a/workshop_app/templates/workshop_app/base.html b/workshop_app/templates/workshop_app/base.html new file mode 100644 index 0000000..391fa9b --- /dev/null +++ b/workshop_app/templates/workshop_app/base.html @@ -0,0 +1,53 @@ +<!DOCTYPE html> +<html> +<head> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <title> + {% block title %} + HomePage + {% endblock %} + </title> + <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> + + <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"> + <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"> + <link href="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"> + + + <link rel="stylesheet" href="{{ URL_ROOT }}/static/workshop_app/css/sticky-footer.css" type="text/css" /> +</head> + + <!-- For js/ajax and other related scripts --> + {% block extra %} + {% endblock %} + +<body style="overflow: scroll;"> + + {% block header %} + <nav class="navbar navbar-default navbar-custom"> + <div class="container-fluid"> + <div class="navbar-header"> + <a class="navbar-brand" href="#">Booking</a> + </div> + <ul class="nav navbar-nav"> + <li class="active"><a href="#">Home</a></li> + </ul> + <ul class="nav navbar-nav navbar-right"> + <li><a href="{{ URL_ROOT }}/register/"><span class="glyphicon glyphicon-user"></span> Register</a></li> + <li><a href="{{ URL_ROOT }}/login/"><span class="glyphicon glyphicon-log-in"></span> Login</a></li> + </ul> + </div> + </nav> + {% endblock %} + + {% block content %} + <h1>Base Template Content. Please override me</h1> + {% endblock %} + + <footer class="footer"> + <div class="container"> + <p align="center">Developed by FOSSEE group, IIT Bombay</p> + </div> + </footer> +</body> +</html>
\ No newline at end of file diff --git a/workshop_app/templates/workshop_app/booking.html b/workshop_app/templates/workshop_app/booking.html new file mode 100644 index 0000000..13af37c --- /dev/null +++ b/workshop_app/templates/workshop_app/booking.html @@ -0,0 +1,178 @@ +{% extends 'workshop_app/base.html' %} + +{% block title %} + Booking +{% endblock %} + + +{% block extra %} + + <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script> + <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script> + + <link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css"> + <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script> + + <script> + // Button function + function sendData(d){ + var check_count; + //For queue + var URL = "{{ URL_ROOT }}/book_workshop/"; + c = d + ',0'; + $.ajax({ + url: URL, + datatype: 'json', + async: false, + type: "POST", + data: { + c, + csrfmiddlewaretoken: $("input[name=csrfmiddlewaretoken]").val() + }, + success:function(response){ + check_count = response; + } + }); + + var $dialog = $('<div></div').html( + '<form id="myform" action="">\ + <input type="checkbox" id="one"\ + name="one" value="one"/> I will give minimum 50 participants for the workshop.<br/>\ + <input type="checkbox" id="two" name="two" value="two" /> I agree that this booking won\'t be cancelled without prior notice to the instructor and fossee.<br/>\ + <input type="checkbox" id="three" name="three" value="three"/> I am '+ check_count +' in the queue.\ + </form> ') + .dialog({ + autoOpen: false, + title: 'Terms & Condition', + buttons: { + "Confirm": function(){ + if($('#one').is(":checked") && $('#two').is(":checked") && $('#three').is(":checked")){ + booking_confirmed(d); + $(this).dialog("close"); + } else { + alert("Please select all the checkboxes."); + } + }, + "Cancel": function(){ + $(this).dialog("close"); + } + } + }); + $dialog.dialog('open'); + } + + function booking_confirmed(d){ + var URL = "{{ URL_ROOT }}/book_workshop/"; + + $.ajax({ + url: URL, + type: "POST", + data: { + d, + csrfmiddlewaretoken: $("input[name=csrfmiddlewaretoken]").val() + }, + + success:function(response){ + window.location.reload(); + alert("success: " + response); + } + }); + } + </script> +{% endblock %} + +{% block header %} + + <nav class="navbar navbar-default navbar-custom"> + <div class="container-fluid"> + <div class="navbar-header"> + <a class="navbar-brand" href="#">Coordinator Profile</a> + </div> + <ul class="nav navbar-nav"> + <li class="active"><a href="{{ URL_ROOT}}/book/">Book</a></li> + <li><a href="{{ URL_ROOT}}/my_workshops/">My Workshops</a></li> + <li><a href="{{ URL_ROOT }}/propose_workshop/">Propose a Workshop</a></li> + </ul> + <ul class="nav navbar-nav navbar-right"> + <li><a href="{{ URL_ROOT }}/view_profile/"><span class="glyphicon glyphicon-user"></span> Profile </a></li> + <li><a href="{{ URL_ROOT }}/logout/"><span class="glyphicon glyphicon-log-out"></span> Logout</a></li> + </ul> + </div> + </nav> +{% endblock %} + +{% block content %} + <h4 align="center">This is the list of events available, if you haved booked a workshop please goto My Workshops and check your workshop status.</h4> + <br> + <div class="container"> + <table class="table table-hover "> + <thead> + <tr> + <th>Instructor Name</th> + <th>Workshop Name</th> + <th>Workshop Day</th> + <th>Booking</th> + </tr> + </thead> + {% csrf_token %} + + {% for workshop in workshop_details %} + <tbody> + + <tr > + <td id="instructor-name">{{ workshop.1 }}</td> + <td class="accordion-toggle" data-toggle="collapse" href="#collapseOne{{ forloop.counter }}" + id="workshop-name">{{ workshop.2 }}<a href="#"> + <span class="glyphicon glyphicon-info-sign"></span> + </a></td> + <td id="workshop-date{{ forloop.counter }}">{{ workshop.0 }}</td> + <td><button class="btn btn-primary btn-sm" id="book-btn" onClick="sendData('{{workshop.0}},{{workshop.3}},{{workshop.4}}')" > Book</button></td> + </tr> + + <tr> + <td colspan="12" class="hiddenRow"> + <div id="collapseOne{{ forloop.counter }}" class="accordion-body collapse"> + <table class="table table-striped"> + <tbody> + <tr> + <td>{{ workshop.5|safe }}</td> + </tr> + </tbody> + </table> + </div> + </td> + </tr> + </tbody> + {% endfor %} + </table> + </div> + + + <!-- Page Navigation --> + <div class="container"> + <div class="Page-Nav" align="center"> + <nav aria-label="Page navigation"> + <ul class="pagination pagination-sm"> + <li class="page-item"> + {% if workshop_details.has_previous %} + <a class="page-link" tabindex="-1" + href="?page={{ workshop_details.previous_page_number }}">Previous</a> + {% endif %} + </li> + <li class="page-item"> + <span class="current"> + Page {{ workshop_details.number }} of {{ workshop_details.paginator.num_pages }} + </span> + </li> + <li class="page-item"> + {% if workshop_details.has_next %} + <a class="page-link" href="?page={{ workshop_details.next_page_number }}">Next + </a> + {% endif %} + </li> + </ul> + </nav> + </div> + </div> + +{% endblock %}
\ No newline at end of file diff --git a/workshop_app/templates/workshop_app/create_workshop.html b/workshop_app/templates/workshop_app/create_workshop.html new file mode 100644 index 0000000..2977a58 --- /dev/null +++ b/workshop_app/templates/workshop_app/create_workshop.html @@ -0,0 +1,45 @@ +{% extends "workshop_app/base.html" %} + +{% block title %} + Create Event +{% endblock %} + + {% block extra %} + <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css"> + + <script src="https://code.jquery.com/jquery-1.12.4.js"></script> + <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script> + {% endblock %} + +{% block header %} + <nav class="navbar navbar-default navbar-custom"> + <div class="container-fluid"> + <div class="navbar-header"> + <a class="navbar-brand" href="#">Instructor Profile</a> + </div> + <ul class="nav navbar-nav"> + <li ><a href="{{ URL_ROOT }}/manage/">Manage</a></li> + <li class="active"><a href="{{ URL_ROOT }}/create_workshop/">Create Workshop</a></li> + <li ><a href="{{ URL_ROOT }}/view_workshoptype_list/">View Workshop List</a></li> + <li ><a href="{{ URL_ROOT }}/my_workshops/">My Workshops</a></li> + </ul> + <ul class="nav navbar-nav navbar-right"> + <li><a href="{{ URL_ROOT }}/view_profile/"><span class="glyphicon glyphicon-user"></span> Profile </a></li> + <li><a href="{{ URL_ROOT }}/logout/"><span class="glyphicon glyphicon-log-out"></span> Logout</a></li> + </ul> + </div> + </nav> +{% endblock %} + +{% block content %} + <div class="container"> + <form method="post"> + {% csrf_token %} + <br/> + {{ form.media }} + {{ form.as_p }} + <br><br> + <button class="btn btn-success" type="submit">Save</button> + </form> + </div> +{% endblock %}
\ No newline at end of file diff --git a/workshop_app/templates/workshop_app/edit_profile.html b/workshop_app/templates/workshop_app/edit_profile.html new file mode 100644 index 0000000..414b931 --- /dev/null +++ b/workshop_app/templates/workshop_app/edit_profile.html @@ -0,0 +1,48 @@ +{% extends "workshop_app/base.html" %} + +{% block title %} + Edit Profile +{% endblock %} + +{% block header %} + <nav class="navbar navbar-default navbar-custom"> + <div class="container-fluid"> + <div class="navbar-header"> + <a class="navbar-brand" href="#">WebSiteName</a> + </div> + {% if request.user.profile.position == 'instructor' %} + <ul class="nav navbar-nav"> + <li><a href="{{ URL_ROOT }}/manage/">Manage</a></li> + <li><a href="{{ URL_ROOT }}/create_workshop/">Create Workshop</a></li> + <li><a href="{{ URL_ROOT }}/view_workshoptype_list/">View Workshop List</a></li> + <li><a href="{{ URL_ROOT }}/my_workshops/">My Workshops</a></li> + </ul> + {% else %} + <ul class="nav navbar-nav"> + <li><a href="{{ URL_ROOT }}/book/">Book</a></li> + <li><a href="{{ URL_ROOT }}/my_workshops/">My Workshops</a></li> + <li><a href="{{ URL_ROOT }}/propose_workshop/">Propose a Workshop</a></li> + </ul> + {% endif %} + <ul class="nav navbar-nav navbar-right"> + <li><a href="{{ URL_ROOT }}/view_profile/"><span class="glyphicon glyphicon-user"></span> Profile </a></li> + <li><a href="{{ URL_ROOT }}/logout/"><span class="glyphicon glyphicon-log-out"></span> Logout</a></li> + </ul> + </div> + </nav> +{% endblock %} + +{% block content %} + <div class="container"> + <form action="{{URL_ROOT}}/edit_profile/" method="post" > + {% csrf_token %} + <center> + <table class="table table-bordered"> + {{ form.as_table }} + </table> + </center> + <br> + <button class="btn btn-primary pull-right" type="submit">Save Profile</button> + </form> + </div> +{% endblock %}
\ No newline at end of file diff --git a/workshop_app/templates/workshop_app/how_to_participate.html b/workshop_app/templates/workshop_app/how_to_participate.html new file mode 100644 index 0000000..0d8cc6f --- /dev/null +++ b/workshop_app/templates/workshop_app/how_to_participate.html @@ -0,0 +1,35 @@ +{% extends 'workshop_app/base.html' %} + +{% block title %} + View Benefits +{% endblock %} + +{% block extra %} + + <!-- <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"> --> + + <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script> + <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script> +{% endblock %} + +{% block header %} + <nav class="navbar navbar-default navbar-custom"> + <div class="container-fluid"> + <div class="navbar-header"> + <a class="navbar-brand" href="{{URL_ROOT}}/">Booking</a> + </div> + <ul class="nav navbar-nav navbar-right"> + <li><a href="{{ URL_ROOT }}/register/"><span class="glyphicon glyphicon-user"></span> Register</a></li> + <li><a href="{{ URL_ROOT }}/login/"><span class="glyphicon glyphicon-log-in"></span> Login</a></li> + </ul> + </div> + </nav> + {% endblock %} + +{% block content %} + + <div class="container-fluid" style="margin-left:auto;"> + <img src="{{ URL_ROOT }}/static/workshop_app/img/img2.jpg"> + </div> + +{% endblock %}
\ No newline at end of file diff --git a/workshop_app/templates/workshop_app/index.html b/workshop_app/templates/workshop_app/index.html new file mode 100644 index 0000000..ed34e4e --- /dev/null +++ b/workshop_app/templates/workshop_app/index.html @@ -0,0 +1,120 @@ +<!DOCTYPE html> +<html> + <head> + <title>Welcome</title> + </head> + + <!-- Bootstrap CDN --> + <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> + + <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"> + <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"> + + <link rel="stylesheet" href="{{ URL_ROOT }}/static/workshop_app/css/index.css" type="text/css" /> + + <body> + <div class="container" style="width: 90%; height:90%;background:#C8C5B6;"> + <div class="row"> + + <div class="col-md-4"> + <div class="fossee-label">FOSSEE Workshop</div> + <div class="logo"> + <img src="{{ URL_ROOT }}/static/workshop_app/img/python_logo.png" > + </div> + </div> + + <div class="login col-md-8"> + <div class="label-bar"><a href="http://python.fossee.in/about/" + target="_blank" style="color: #6D5847;">About </a>|<a href="" style="color: #6D5847;">Blog </a>| <a href="http://python.fossee.in/gallery/" target="_blank" style="color: #6D5847;">Gallery</a></div> + <img src=" {{ URL_ROOT }}/static/workshop_app/img/img_1.png" style="margin-left: 40%;padding-top: 25%;"><br> + <div id="rectbox"> + + <form method="post"> + {% csrf_token %} + {{ form.as_p }} + <button class="btn btn-default btn-sm" style="margin-left: 35%;" type="submit">Login</button> + <br> + </form> + </div> + + <h4 style="margin-left: 27%; color: grey;">If not Registered yet, <br> please <a href="{{ URL_ROOT}}/register/" target="_blank">register here.</a></h4> + <br><br> + + </div> + + </div> + + <div class="row"> + <div class="icons col-sm-12"> + + <figure class="item" style="margin-left: 10%;"> + <a href="{{ URL_ROOT }}/view_workshoptype_details/" style="color: #6D5847;"> + <img class="caption-img" src="{{ URL_ROOT }}/static/workshop_app/img/list.png" > + <figcaption class="caption">Course List</figcaption> + </a> + </figure> + + <figure class="item" style="margin-left: 15%;"> + <a href="{{ URL_ROOT }}/benefits/" style="color: #6D5847;"> + <img class="caption-img" src="{{ URL_ROOT }}/static/workshop_app/img/bnft.png" > + <figcaption class="caption" >Benefits</figcaption> + </a> + </figure> + + <figure class="item" style="margin-left: 15%;"> + <a href="{{ URL_ROOT }}/faq/" style="color: #6D5847;"> + <img class="caption-img" src="{{ URL_ROOT }}/static/workshop_app/img/faq.png" > + <figcaption class="caption" >FAQs</figcaption> + </a> + </figure> + + <figure class="item" style="margin-left: 15%; "> + <a href="{{ URL_ROOT }}/how_to_participate/" style="color: #6D5847;"> + <img class="caption-img" src="{{ URL_ROOT }}/static/workshop_app/img/part.png" > + <figcaption class="caption">How to Participate</figcaption> + </a> + </figure> + + </div> + </div> + + + <!-- Bottom 3 cols --> + <div class="row"> + <!-- Logo --> + <div class="org-logo col-sm-4"> + <span >Organized By:</span><br> + <img src="{{ URL_ROOT }}/static/workshop_app/img/fossee_logo.png"> + + <img src="{{ URL_ROOT }}/static/workshop_app/img/iitb_logo.png" > + <br> + </div> + + <!-- Related Links --> + <div class="related-links col-sm-4"> + Related Links<br> + <a href="http://fossee.in" target="_blank" >fossee.in</a><br> + <a href="http://yaksh.fossee.in" target="_blank" >yaksh.fossee.in</a><br> + <a href="http://python.fossee.in" target="_blank" >python.fossee.in</a> + </div> + + <!-- Contact Us --> + <div class="contact-us col-sm-4"> + Contact Us:<br> + FOSSEE, IIT-Bombay<br> + Mumbai, India<br> + + Phone: (+91) 22 2576 + 4133<br> + Email: info[at]fossee[dot]in + </div> + </div> + + + <div class="footer"> + <img src="{{ URL_ROOT }}/static/workshop_app/img/cc.png" style="width:5%;height:3%;"> + This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License + </div> + </div> + </body> +</html> diff --git a/workshop_app/templates/workshop_app/login.html b/workshop_app/templates/workshop_app/login.html new file mode 100644 index 0000000..47f5827 --- /dev/null +++ b/workshop_app/templates/workshop_app/login.html @@ -0,0 +1,35 @@ +{% extends 'workshop_app/base.html' %} + + {% block title %} + Login + {% endblock %} + +{% block header %} + <nav class="navbar navbar-default navbar-custom"> + <div class="container-fluid"> + <div class="navbar-header"> + <a class="navbar-brand" href="{{ URL_ROOT }}/">Booking</a> + </div> + + <ul class="nav navbar-nav navbar-right"> + <li><a href="{{ URL_ROOT }}/register/"><span class="glyphicon glyphicon-user"></span> Register</a></li> + <li><a href="{{ URL_ROOT }}/login/"><span class="glyphicon glyphicon-log-in"></span> Login</a></li> + </ul> + </div> + </nav> + {% endblock %} + + {% block content %} + <div class="container" align="center"> + <br> + <form method="post"> + {% csrf_token %} + {{ form.as_p }} + <br> + <br> + <button class="btn btn-default" type="submit">Login</button> + <br> + </form> + <br> + </div> + {% endblock %} diff --git a/workshop_app/templates/workshop_app/logout.html b/workshop_app/templates/workshop_app/logout.html new file mode 100644 index 0000000..5dd9587 --- /dev/null +++ b/workshop_app/templates/workshop_app/logout.html @@ -0,0 +1,31 @@ +{% extends 'workshop_app/base.html' %} + + {% block title %} + Logged out + {% endblock %} + +{% block header %} + <nav class="navbar navbar-default navbar-custom"> + <div class="container-fluid"> + <div class="navbar-header"> + <a class="navbar-brand" href="{{ URL_ROOT }}/">Booking</a> + </div> + + <ul class="nav navbar-nav navbar-right"> + <li><a href="{{ URL_ROOT }}/register/"><span class="glyphicon glyphicon-user"></span> Register</a></li> + <li><a href="{{ URL_ROOT }}/login/"><span class="glyphicon glyphicon-log-in"></span> Login</a></li> + </ul> + </div> + </nav> + {% endblock %} + + + {% block content %} + <div class="container" align="center"> + <br> + <h3>You have logged out successfully.</h3> + <h4>If you want to Login again please <a href="{{ URL_ROOT}}/login/">click here</a></h4> + <br> + </div> + + {% endblock %}
\ No newline at end of file diff --git a/workshop_app/templates/workshop_app/manage.html b/workshop_app/templates/workshop_app/manage.html new file mode 100644 index 0000000..e210e5e --- /dev/null +++ b/workshop_app/templates/workshop_app/manage.html @@ -0,0 +1,129 @@ +{% extends 'workshop_app/base.html' %} + +{% block header %} + <nav class="navbar navbar-default navbar-custom"> + <div class="container-fluid"> + <div class="navbar-header"> + <a class="navbar-brand" href="#">Instructor Profile</a> + </div> + <ul class="nav navbar-nav"> + <li class="active"><a href="{{ URL_ROOT }}/manage/">Manage</a></li> + <li ><a href="{{ URL_ROOT }}/create_workshop/">Create Workshop</a></li> + <li ><a href="{{ URL_ROOT }}/view_workshoptype_list/">View Workshop List</a></li> + <li ><a href="{{ URL_ROOT }}/my_workshops/">My Workshops</a></li> + </ul> + <ul class="nav navbar-nav navbar-right"> + <li><a href="{{ URL_ROOT }}/view_profile/"><span class="glyphicon glyphicon-user"></span> Profile </a></li> + <li><a href="{{ URL_ROOT }}/logout/"><span class="glyphicon glyphicon-log-out"></span> Logout</a></li> + </ul> + </div> + </nav> +{% endblock %} + +{% block extra %} + <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script> + <link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css"> + <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script> + <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script> + <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script> + <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script> + <script> + //ToolTip PopUp function onhover + $(document).ready(function(){ + $('[data-toggle="popover"]').popover({ + placement : 'top', + trigger : 'hover' + }); + }); + + function sendData(d){ + var URL = "{{ URL_ROOT }}/my_workshops/" + console.log(d); + $.ajax({ + url: URL, + type: "POST", + dataType: 'json', + data: { + d, + csrfmiddlewaretoken: $("input[name=csrfmiddlewaretoken]").val() + }, + }); + + window.location.reload(); + alert("Refreshing Page please wait, if you don't see your changes, please refresh this page again."); + } + </script> + + +{% endblock %} + + +{% block content %} + + {% if workshop_occurence_list %} + <h4 align="center">This is the list of workshops you have created, you can delete a workshop if you are not availble on that day. </h4> + <br> + <div class="container"> + <table class="table table-hover"> + <thead> + <tr> + <th>Instructor Name</th> + <th>Workshop Name</th> + <th>Workshop Day</th> + </tr> + </thead> + {% csrf_token %} + {% for w in workshop_occurence_list %} + <tbody> + <tr> + <td>{{ w.user }}</td> + <td>{{ w.workshop }}</td> + <td>{{ w.date | date}}</td> + <td><button class="btn btn-danger btn-sm" id="delete-btn" onClick="sendData('{{ w.user}},{{w.date | safe}},{{ w.workshop.id }},DELETED')" data-toggle="popover" title="Please Note" data-content="Once Deleted you cannot revoke this action." > Delete Workshop </button></td> + </tr> + </tbody> + {% endfor %} + </table> + </div> + +<!-- Page Navigation --> + <div class="container"> + <div class="Page-Nav" align="center"> + <nav aria-label="Page navigation"> + <ul class="pagination pagination-sm"> + <li class="page-item"> + {% if workshop_occurence_list.has_previous %} + <a class="page-link" tabindex="-1" + href="?page={{ workshop_occurence_list.previous_page_number }}">Previous</a> + {% endif %} + </li> + <li class="page-item"> + <span class="current"> + Page {{ workshop_occurence_list.number }} of {{ workshop_occurence_list.paginator.num_pages }} + </span> + </li> + <li class="page-item"> + {% if workshop_occurence_list.has_next %} + <a class="page-link" href="?page={{ workshop_occurence_list.next_page_number }}">Next + </a> + {% endif %} + </li> + </ul> + </nav> + </div> + </div> + + {% else %} + <div class="container"> + <div class="jumbotron"> + <h1>Welcome Instructor</h1> + <p>Please navigate to <b>View Workshop list</b> and depending upon + your expertise and availability create a workshop by going to + <b>Create Workshop</b>. you can also check any workshop + requests by going to <b>My Workshops</b></p> + + </div> + </div> + {% endif %} + +{% endblock %}
\ No newline at end of file diff --git a/workshop_app/templates/workshop_app/my_workshops.html b/workshop_app/templates/workshop_app/my_workshops.html new file mode 100644 index 0000000..275a0a0 --- /dev/null +++ b/workshop_app/templates/workshop_app/my_workshops.html @@ -0,0 +1,295 @@ +{% extends "workshop_app/base.html" %} + +{% block title %} + My Workshops +{% endblock %} + +{% block extra %} + <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script> + <link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css"> + <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script> + <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script> + <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script> + <script> + //ToolTip popup function onhover + $(document).ready(function(){ + $('[data-toggle="popover"]').popover({ + placement : 'top', + trigger : 'hover' + }); + }); + + function sendData(d){ + var URL = "{{ URL_ROOT }}/my_workshops/" + console.log(d); + $.ajax({ + url: URL, + type: "POST", + dataType: 'json', + data: { + d, + csrfmiddlewaretoken: $("input[name=csrfmiddlewaretoken]").val() + }, + }); + + window.location.reload(); + alert("Refreshing Page please wait, if you don't see your changes, please refresh this page again."); + } + </script> +{% endblock %} + +{% block header %} + <nav class="navbar navbar-default navbar-custom"> + <div class="container-fluid"> + {% if request.user.profile.position == 'instructor' %} + <div class="navbar-header"> + <a class="navbar-brand" href="#">Instructor Profile</a> + </div> + <ul class="nav navbar-nav"> + <li><a href="{{ URL_ROOT }}/manage/">Manage</a></li> + <li><a href="{{ URL_ROOT }}/create_workshop/">Create Workshop</a></li> + <li><a href="{{ URL_ROOT }}/view_workshoptype_list/">View Workshop List</a></li> + <li class="active"><a href="{{ URL_ROOT }}/my_workshops/">My Workshops</a></li> + </ul> + {% else %} + <div class="navbar-header"> + <a class="navbar-brand" href="{{URL_ROOT}}/book/">Coordinator Profile</a> + </div> + <ul class="nav navbar-nav"> + <li><a href="{{ URL_ROOT }}/book/">Book</a></li> + <li class="active"><a href="{{ URL_ROOT }}/my_workshops/">My Workshops</a></li> + <li><a href="{{ URL_ROOT }}/propose_workshop/">Propose a Workshop</a></li> + </ul> + {% endif %} + + <ul class="nav navbar-nav navbar-right"> + <li><a href="{{ URL_ROOT }}/view_profile/"><span class="glyphicon glyphicon-user"></span> Profile </a></li> + <li><a href="{{ URL_ROOT }}/logout/"><span class="glyphicon glyphicon-log-out"></span> Logout</a></li> + </ul> + </div> + </nav> +{% endblock %} + + +{% block content %} +{% if workshop_occurences %} + <h3 align="center">The status of your workshops </h3> + <br> + + <!-- Pending View --> + <div class="container"> + <h3 align="center"><strong><u>Pending</u></strong></h3> + <table class="table table-striped"> + <thead> + <tr> + {% if request.user.profile.position == 'instructor' %} + <th>Coordinator Name</th> + {% else %} + <th>Instructor Name</th> + {% endif %} + <th>Workshop Name</th> + <th>Workshop Day</th> + <th>Status</th> + </tr> + </thead> + {% csrf_token %} + {% for workshop in workshop_occurences %} + <tbody> + <tr> + {% if workshop.status == 'Pending' and workshop.requested_workshop_instructor %} + {% if request.user.profile.position == 'instructor' %} + <td>{{ workshop.requested_workshop_coordinator }}</td> + {% else %} + <td>{{ workshop.requested_workshop_instructor }}</td> + {% endif %} + <td>{{ workshop.requested_workshop_title }}</td> + <td>{{ workshop.requested_workshop_date }}</td> + <td><span class = "label label-warning">{{ workshop.status }}</span></td> + {% endif %} + {% if request.user.profile.position == 'instructor' and workshop.status == 'Pending' and workshop.requested_workshop_instructor %} + <td><button class="btn btn-primary btn-sm" id="book-btn" onClick="sendData('{{workshop.requested_workshop_coordinator}},{{workshop.requested_workshop_date| safe}},{{ workshop.requested_workshop_title_id }},ACCEPTED')" data-toggle="popover" title="Please Note" data-content="Once Accepted you can't Reject, you have to personally contact the Coordinator if the workshop is to be cancelled"> Accept</button></td> + <td><button class="btn btn-danger btn-sm" id="book-btn" onClick="sendData('{{workshop.requested_workshop_coordinator}},{{workshop.requested_workshop_date| safe}},{{ workshop.requested_workshop_title_id }},REJECTED')" data-toggle="popover" title="Please Note" data-content="Once Rejected you cannot revoke this action."> Reject </button></td> + {% endif %} + </tr> + </tbody> + + {% endfor %} + </table> + </div> + + <!-- Accepted View --> + <div class="container"> + <h3 align="center"><strong><u>Accepted</u></strong></h3> + <table class="table table-striped"> + <thead> + <tr> + {% if request.user.profile.position == 'instructor' %} + <th>Coordinator Name</th> + {% else %} + <th>Instructor Name</th> + {% endif %} + <th>Workshop Name</th> + <th>Workshop Day</th> + <th>Status</th> + </tr> + </thead> + {% csrf_token %} + {% for workshop in workshop_occurences %} + <tbody> + <tr> + {% if workshop.status == 'ACCEPTED' and workshop.requested_workshop_title %} + {% if request.user.profile.position == 'instructor' %} + <td>{{ workshop.requested_workshop_coordinator }}</td> + {% else %} + <td>{{ workshop.requested_workshop_instructor }}</td> + {% endif %} + <td>{{ workshop.requested_workshop_title }}</td> + <td>{{ workshop.requested_workshop_date }}</td> + <td><span class = "label label-success">{{ workshop.status }}</span></td> + {% endif %} + {% if workshop.status == 'ACCEPTED' and workshop.conditionone %} + {% if request.user.profile.position == 'instructor' %} + <td>{{ workshop.proposed_workshop_coordinator }}</td> + {% else %} + <td>{{ workshop.proposed_workshop_instructor }}</td> + {% endif %} + <td>{{ workshop.proposed_workshop_title }}</td> + <td>{{ workshop.proposed_workshop_date }}</td> + <td><span class = "label label-success">{{ workshop.status }}</span></td> + {% endif %} + </tr> + </tbody> + + {% endfor %} + + </table> + </div> + + +<!-- Proposed View --> +<div class="container"> + <h3 align="center"><strong><u>Proposed</u></strong></h3> + <table class="table table-striped"> + <thead> + <tr> + {% if request.user.profile.position == 'instructor' %} + <th>Coordinator Name</th> + {% else %} + + {% endif %} + <th>Workshop Name</th> + <th>Workshop Day</th> + <th>Status</th> + </tr> + </thead> + {% csrf_token %} + {% for workshop in workshop_occurences %} + <tbody> + <tr> + {% if workshop.status == 'Pending' and workshop.conditionone %} + {% if request.user.profile.position == 'instructor' %} + <td>{{ workshop.proposed_workshop_coordinator }}</td> + {% endif %} + <td>{{ workshop.proposed_workshop_title }}</td> + <td>{{ workshop.proposed_workshop_date }}</td> + + <td><span class = "label label-warning">{{ workshop.status }}</span></td> + {% if request.user.profile.position == 'instructor' and workshop.status == 'Pending' %} + <td><button class="btn btn-primary btn-sm" id="book-btn" onClick="sendData('{{workshop.proposed_workshop_coordinator}},{{workshop.proposed_workshop_date| safe}},{{ workshop.proposed_workshop_title_id }},APPROVED')" data-toggle="popover" title="Please Note" data-content="Once Accepted you can't Reject, you have to personally contact the Coordinator if the workshop is to be cancelled"> Accept</button></td> + {% endif %} + {% endif %} + </tr> + </tbody> + + {% endfor %} + </table> + </div> + + +<!-- Deleted/Rejected View --> +<div class="container"> + <h3 align="center"><strong><u>Deleted/Rejected</u></strong></h3> + <table class="table table-striped"> + <thead> + <tr> + {% if request.user.profile.position == 'instructor' %} + <th>Coordinator Name</th> + {% else %} + <th>Instructor Name</th> + {% endif %} + <th>Workshop Name</th> + <th>Workshop Day</th> + <th>Status</th> + </tr> + </thead> + {% csrf_token %} + {% for workshop in workshop_occurences %} + <tbody> + <tr> + {% if workshop.status == 'DELETED' or workshop.status == 'REJECTED' %} + {% if request.user.profile.position == 'instructor' %} + <td>{{ workshop.requested_workshop_coordinator }}</td> + {% else %} + <td>{{ workshop.requested_workshop_instructor }}</td> + {% endif %} + <td>{{ workshop.requested_workshop_title }}</td> + <td>{{ workshop.requested_workshop_date }}</td> + + <td><span class = "label label-danger">{{ workshop.status }}</span></td> + {% endif %} + </tr> + </tbody> + + {% endfor %} + </table> + </div> + +<!-- Page Navigation --> + <div class="container"> + <div class="Page-Nav" align="center"> + <nav aria-label="Page navigation"> + <ul class="pagination pagination-sm"> + <li class="page-item"> + {% if workshop_occurences.has_previous %} + <a class="page-link" tabindex="-1" + href="?page={{ workshop_occurences.previous_page_number }}">Previous</a> + {% endif %} + </li> + <li class="page-item"> + <span class="current"> + Page {{ workshop_occurences.number }} of {{ workshop_occurences.paginator.num_pages }} + </span> + </li> + <li class="page-item"> + {% if workshop_occurences.has_next %} + <a class="page-link" href="?page={{ workshop_occurences.next_page_number }}">Next + </a> + {% endif %} + </li> + </ul> + </nav> + </div> + </div> + +{% else %} + {% if request.user.profile.position == 'instructor' %} + <div class="container"> + <div class="jumbotron"> + <h1>Welcome Instructor</h1> + <p>Your workshop related information will be shown here, Please navigate to <b>View Workshop list</b> and depending upon + your expertise and availability create a workshop by going to + <b>Create Workshop</b>.</p> + </div> + </div> + {% else %} + <div class="container"> + <div class="jumbotron"> + <h1>Welcome Coordinator</h1> + <p>Information Related to your workshops will be shown here, you can also + propose a Workshop as per your available date in <strong>Propose a Workshop tab</strong> .</p> + </div> + </div> + {% endif %} +{% endif %} + +{% endblock %}
\ No newline at end of file diff --git a/workshop_app/templates/workshop_app/profile_updated.html b/workshop_app/templates/workshop_app/profile_updated.html new file mode 100644 index 0000000..c90e176 --- /dev/null +++ b/workshop_app/templates/workshop_app/profile_updated.html @@ -0,0 +1,40 @@ +{% extends "workshop_app/base.html" %} + +{% block title %} + Profile Changing +{% endblock %} + +{% block header %} + <nav class="navbar navbar-default navbar-custom"> + <div class="container-fluid"> + <div class="navbar-header"> + <a class="navbar-brand" href="#">WebSiteName</a> + </div> + <ul class="nav navbar-nav"> + {% if request.user.profile.position == 'instructor' %} + <li><a href="{{ URL_ROOT }}/manage/">Manage</a> + </li> + <li><a href="{{ URL_ROOT }}/create_workshop/">Create Workshop</a></li> + {% else %} + <li><a href="{{ URL_ROOT }}/book/">Book</a></li> + <li><a href="{{ URL_ROOT }}/propose_workshop/">Propose a Workshop</a></li> + {% endif %} + <li><a href="{{ URL_ROOT }}/view_workshoptype_list/">View Workshop Details</a></li> + <li><a href="{{ URL_ROOT }}/my_workshops/">My Workshops</a></li> + </ul> + <ul class="nav navbar-nav navbar-right"> + <li><a href="{{ URL_ROOT }}/view_profile/"><span class="glyphicon glyphicon-user"></span> Profile </a></li> + <li><a href="{{ URL_ROOT }}/logout/"><span class="glyphicon glyphicon-log-out"></span> Logout</a></li> + </ul> + </div> + </nav> +{% endblock %} + +{% block content %} + <div class="container"> + <div class="jumbotron"> + <h3>Your Profile has changed {{ user.first_name }}</h3> + </div> + </div> +{% endblock %} + diff --git a/workshop_app/templates/workshop_app/propose_workshop.html b/workshop_app/templates/workshop_app/propose_workshop.html new file mode 100644 index 0000000..697fe63 --- /dev/null +++ b/workshop_app/templates/workshop_app/propose_workshop.html @@ -0,0 +1,54 @@ +{% extends "workshop_app/base.html" %} + +{% block title %} + Propose a workshop +{% endblock %} + + {% block extra %} + <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css"> + + <script src="https://code.jquery.com/jquery-1.12.4.js"></script> + <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script> + + <script> + $(function() { + $( ".datepicker" ).datepicker({ + changeMonth: true, + changeYear: true, + yearRange: "1994:2049", + // You can put more options here. + }); + }); + </script> + {% endblock %} + +{% block header %} + <nav class="navbar navbar-default navbar-custom"> + <div class="container-fluid"> + <div class="navbar-header"> + <a class="navbar-brand" href="{{ URL_ROOT}}/book/">Coordinator Profile</a> + </div> + <ul class="nav navbar-nav"> + <li><a href="{{ URL_ROOT }}/book/">Book</a></li> + <li><a href="{{ URL_ROOT }}/my_workshops/">My Workshops</a></li> + <li class="active"><a href="{{ URL_ROOT }}/propose_workshop/">Propose a Workshop</a></li> + </ul> + <ul class="nav navbar-nav navbar-right"> + <li><a href="{{ URL_ROOT }}/view_profile/"><span class="glyphicon glyphicon-user"></span> Profile </a></li> + <li><a href="{{ URL_ROOT }}/logout/"><span class="glyphicon glyphicon-log-out"></span> Logout</a></li> + </ul> + </div> + </nav> +{% endblock %} + +{% block content %} + <div class="container"> + <form method="post"> + {% csrf_token %} + <br/> + {{ form.as_p }} + <br><br> + <button class="btn btn-success" type="submit">Submit</button> + </form> + </div> +{% endblock %}
\ No newline at end of file diff --git a/workshop_app/templates/workshop_app/register.html b/workshop_app/templates/workshop_app/register.html new file mode 100644 index 0000000..6e688d5 --- /dev/null +++ b/workshop_app/templates/workshop_app/register.html @@ -0,0 +1,40 @@ +{% extends 'workshop_app/base.html' %} + + {% block title %} + Register + {% endblock %} + + {% block header %} + <nav class="navbar navbar-default navbar-custom"> + <div class="container-fluid"> + <div class="navbar-header"> + <a class="navbar-brand" href="{{ URL_ROOT }}/">Booking</a> + </div> + + <ul class="nav navbar-nav navbar-right"> + <li class="active"><a href="{{ URL_ROOT }}/register/"><span class="glyphicon glyphicon-user"></span> Register</a></li> + <li><a href="{{ URL_ROOT }}/login/"><span class="glyphicon glyphicon-log-in"></span> Login</a></li> + </ul> + </div> + </nav> + {% endblock %} + +{% block content %} + <style type="text/css"> + label.required::after { + content: "*"; + color: red; + } + </style> + + <div class="container" > + <br> + <form action="" method="post"> + {% csrf_token %} + <table class="table table-bordered"> + {{ form.as_table }} + </table> + <button class="btn btn-primary" type="submit">Register</button> + </form> + </div> +{% endblock %} diff --git a/workshop_app/templates/workshop_app/registeration_error.html b/workshop_app/templates/workshop_app/registeration_error.html new file mode 100644 index 0000000..ad1e73b --- /dev/null +++ b/workshop_app/templates/workshop_app/registeration_error.html @@ -0,0 +1,13 @@ +{% extends 'workshop_app/base.html' %} + +{% block title %} + Registeration Error +{% endblock %} + +{% block content %} + <div class="container" > + <br> + <h1>Error Occurred While registration</h1> + <h3>Please try to <a href="{{ URL_ROOT }}/register/"> register again</a> using different username or email and see to it that you fill all the fields.</h3> + </div> +{% endblock %}
\ No newline at end of file diff --git a/workshop_app/templates/workshop_app/view_benefits.html b/workshop_app/templates/workshop_app/view_benefits.html new file mode 100644 index 0000000..9b56244 --- /dev/null +++ b/workshop_app/templates/workshop_app/view_benefits.html @@ -0,0 +1,48 @@ +{% extends 'workshop_app/base.html' %} + +{% block title %} + View Benefits +{% endblock %} + +{% block extra %} + + <!-- <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"> --> + + <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script> + <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script> +{% endblock %} + +{% block header %} + <nav class="navbar navbar-default navbar-custom"> + <div class="container-fluid"> + <div class="navbar-header"> + <a class="navbar-brand" href="{{URL_ROOT}}/">Booking</a> + </div> + <ul class="nav navbar-nav navbar-right"> + <li><a href="{{ URL_ROOT }}/register/"><span class="glyphicon glyphicon-user"></span> Register</a></li> + <li><a href="{{ URL_ROOT }}/login/"><span class="glyphicon glyphicon-log-in"></span> Login</a></li> + </ul> + </div> + </nav> + {% endblock %} + +{% block content %} + + <div class="container"> + <h1>Features and Benefits:</h1><br> + <p><h4> + The workshops can be arranged at your convenience. + Hands-on experience in Python programming with many practice sessions and quizzes. + Certificates and honorarium will be provided on successful completion. + </h4></p> + <br> + <p><h4> + Hone your programming skills in Python. + Live video/chat assistance from FOSSEE Python experts + Closely integrated with online programming evaluation tool. + Designed, developed, and presented by Prof.Prabhu Ramachandran and the FOSSEE team at IIT Bombay + </h4></p> + <br><br> + </div> + +{% endblock %}
\ No newline at end of file diff --git a/workshop_app/templates/workshop_app/view_faq.html b/workshop_app/templates/workshop_app/view_faq.html new file mode 100644 index 0000000..77ec095 --- /dev/null +++ b/workshop_app/templates/workshop_app/view_faq.html @@ -0,0 +1,150 @@ +{% extends 'workshop_app/base.html' %} + +{% block title %} + FAQ'S +{% endblock %} + +{% block extra %} + <link rel="stylesheet" href="{{ URL_ROOT }}/static/workshop_app/css/faq.css" type="text/css" /> + <!-- <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"> --> + + <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script> + <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script> + <link href='//fonts.googleapis.com/css?family=Antic Slab' rel='stylesheet'> + +{% endblock %} + +{% block header %} + <nav class="navbar navbar-default navbar-custom"> + <div class="container-fluid"> + <div class="navbar-header"> + <a class="navbar-brand" href="{{URL_ROOT}}/">Booking</a> + </div> + <ul class="nav navbar-nav navbar-right"> + <li><a href="{{ URL_ROOT }}/register/"><span class="glyphicon glyphicon-user"></span> Register</a></li> + <li><a href="{{ URL_ROOT }}/login/"><span class="glyphicon glyphicon-log-in"></span> Login</a></li> + </ul> + </div> + </nav> + {% endblock %} + +{% block content %} + + <div class="container"> + <h1>FAQs-</h1><br> + <ul class='num'> + <li class='ans'> + Who can participate in these workshops?<br> + + Anyone interested in learning Python irrespective of their domain can participate. + </li> + </ul> + + <ul class='num'> + <li class='ans'> + Will the participants receive certificates?<br> + Yes, graded certificates shall be issued only after successfully clearing our post-workshop assessments/tests. + </li> + </ul> + + <ul class='num'> + <li class='ans'> + Will the coordinators receive certificates?<br> + Yes, even the coordinators of the workshops are awarded certificates. + </li> + </ul> + + <ul class='num'> + <li class='ans'> + When will I get my certificate?<br> + Within 15 working days from the last day of the workshop. + </li> + </ul> + + <ul class='num'> + <li class='ans'> + How many coordinators are required to conduct a workshop?<br> + One coordinator for 50 participants. + </li> + </ul> + + <ul class='num'> + <li class='ans'> + Do we have to pay for the workshop?<br> + Yes, there is a minimal fee to be paid by the students participating in the workshop. + </li> + </ul> + + <ul class='num'> + <li class='ans'> + Do I have to register?<br> + Yes, only the coordinator of the workshop will have to register. + </li> + </ul> + + <ul class='num'> + <li class='ans'> + Can we conduct this workshop as per our convenience?<br> + Absolutely! You may conduct the workshop as per your lab availability. + </li> + </ul> + + <ul class='num'> + <li class='ans'> + What is the approximate wait time after requesting for a workshop?<br> + It could be between 1-2 weeks (subject to availability of our instructors). + </li> + </ul> + + <ul class='num'> + <li class='ans'> + How will the workshop be conducted?<br> + It will be a hands-on workshop with remote assistance by a FOSSEE instructor at IIT Bombay. + </li> + </ul> + + <ul class='num'> + <li class='ans'> + Could we have the instructor at our institute for the workshop?<br> + Unfortunately, we will not be able to send our instructor(s) to your institute. + </li> + </ul> + + <ul class='num'> + <li class='ans'> + I am from a non-technical background but wish to learn Python. Can I participate in this workshop?<br> + Yes, of course. This is open to anyone from any field who is interested in learning Python. + </li> + </ul> + + <ul class='num'> + <li class='ans'> + Can I use the material of this workshop in my class?<br> + Sure, you can use our video lectures. + </li> + </ul> + + <ul class='num'> + <li class='ans'> + Are these workshops provided to individuals as well?<br> + Currently, this program is exclusively available for institutes only. However, if you are not associated with an institute and are willing to participate in this workshop, please write to us at workshops[at]fossee[dot]in + </li> + </ul> + + <ul class='num'> + <li class='ans'> + What are the equipments required for conducting this workshop?<br> + A room with projector, speaker, microphone, laptops/desktops for every participant, high-speed internet and one laptop with a webcam. + </li> + </ul> + + <ul class='num'> + <li class='ans'> + What are the video-audio conferencing tools used for this workshop?<br> + We will use any of these tools: Skype, appear.in and hangouts + </li> + </ul> + </div> + + +{% endblock %}
\ No newline at end of file diff --git a/workshop_app/templates/workshop_app/view_profile.html b/workshop_app/templates/workshop_app/view_profile.html new file mode 100644 index 0000000..751cc0b --- /dev/null +++ b/workshop_app/templates/workshop_app/view_profile.html @@ -0,0 +1,76 @@ +{% extends 'workshop_app/base.html' %} + +{% block title %} + View Profile +{% endblock %} + +{% block header %} + <nav class="navbar navbar-default navbar-custom"> + <div class="container-fluid"> + {% if request.user.profile.position == 'instructor' %} + <div class="navbar-header"> + <a class="navbar-brand" href="#">Instructor Profile</a> + </div> + <ul class="nav navbar-nav"> + <li><a href="{{ URL_ROOT }}/manage/">Manage</a></li> + <li><a href="{{ URL_ROOT }}/create_workshop/">Create Workshop</a></li> + <li><a href="{{ URL_ROOT }}/view_workshoptype_list/">View Workshop List</a></li> + <li><a href="{{ URL_ROOT }}/my_workshops/">My Workshops</a></li> + </ul> + {% else %} + <div class="navbar-header"> + <a class="navbar-brand" href="{{URL_ROOT}}/book/">Coordinator Profile</a> + </div> + <ul class="nav navbar-nav"> + <li><a href="{{ URL_ROOT }}/book/">Book</a></li> + <li><a href="{{ URL_ROOT }}/my_workshops/">My Workshops</a> + <li><a href="{{ URL_ROOT }}/propose_workshop/">Propose a Workshop</a></li></li> + </ul> + {% endif %} + + <ul class="nav navbar-nav navbar-right"> + <li class="active"><a href="{{ URL_ROOT }}/view_profile/"><span class="glyphicon glyphicon-user"></span> Profile </a></li> + <li><a href="{{ URL_ROOT }}/logout/"><span class="glyphicon glyphicon-log-out"></span> Logout</a></li> + </ul> + </div> + </nav> +{% endblock %} + +{% csrf_token %} +{% block content %} + + <div class="container"> + <table class="table table-bordered"> + <tr> + <th><label for="id_first_name"><h5>First name:</h5></label></th> + <th><label for="id_first_name"><h5>{{ user.first_name }}</h5></label></th> + </tr> + <tr> + <th><label for="id_last_name"><h5>Last name:</h5></label></th> + <th><label for="id_last_name"><h5>{{ user.last_name }}</h5></label></th> + </tr> + <tr> + <th><label for="id_email"><h5>Email:</h5></label></th> + <th><label for="id_email"><h5>{{ user.email }}</h5></label></th> + </tr> + <tr> + <th><label for="id_institute"><h5>Institute:</h5></label></th> + <th><label for="id_institute"><h5>{{ user.profile.institute }}</h5></label></th> + </tr> + <tr> + <th><label for="id_phone_number"><h5>Phone Number:</h5></label></th> + <th><label for="id_phone_number"><h5>{{ user.profile.phone_number }}</h5></label></th> + </tr> + <tr> + <th><label for="id_department"><h5>Department:</h5></label></th> + <th><label for="id_department"><h5>{{ user.profile.department }}</h5></label></th> + </tr> + <tr> + <th><label for="id_position"><h5>Position:</h5></label></th> + <th><label for="id_position"><h5>{{ user.profile.position }}</h5></label></th> + </tr> + </table> + <br> + <a class="btn btn-primary pull-right" href="{{ URL_ROOT }}/edit_profile/">Edit Profile</a> + </div> +{% endblock %} diff --git a/workshop_app/templates/workshop_app/view_workshoptype_details.html b/workshop_app/templates/workshop_app/view_workshoptype_details.html new file mode 100644 index 0000000..0cb989e --- /dev/null +++ b/workshop_app/templates/workshop_app/view_workshoptype_details.html @@ -0,0 +1,97 @@ +{% extends 'workshop_app/base.html' %} + +{% block title %} + View Details About Workshops +{% endblock %} + +{% block extra %} + + <!-- <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"> --> + + <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script> + <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script> +{% endblock %} + +{% block header %} + <nav class="navbar navbar-default navbar-custom"> + <div class="container-fluid"> + <div class="navbar-header"> + <a class="navbar-brand" href="{{URL_ROOT}}/">Booking</a> + </div> + <ul class="nav navbar-nav navbar-right"> + <li><a href="{{ URL_ROOT }}/register/"><span class="glyphicon glyphicon-user"></span> Register</a></li> + <li><a href="{{ URL_ROOT }}/login/"><span class="glyphicon glyphicon-log-in"></span> Login</a></li> + </ul> + </div> + </nav> + {% endblock %} + +{% block content %} + + <div class="container"> + + <table class="table table-hover" style="border-collapse:collapse;"> + <thead> + <tr> + <th>id</th> + <th>Workshop Name</th> + <th>Workshop Duration</th> + </tr> + </thead> + + {% for w in workshoptype %} + <tbody> + <tr > + <td scope="row" id="{{ forloop.counter }}">{{ forloop.counter }}</td> + <td>{{ w.workshoptype_name }}</td> + <td>{{ w.workshoptype_duration }}</td> + <td><button class="btn btn-default btn-sm" class="accordion-toggle" data-toggle="collapse" href="#collapseOne{{ forloop.counter }}">View Workshop Details</button></td> + </tr> + + <tr> + <td colspan="12" class="hiddenRow"> + <div id="collapseOne{{ forloop.counter }}" class="accordion-body collapse"> + <table class="table table-striped"> + <tbody> + <tr> + <td>{{ w.workshoptype_description|safe }}</td> + </tr> + </tbody> + </table> + </div> + </td> + </tr> + </tbody> + {% endfor %} + </table> + + </div> + +<!-- Page Navigation --> + <div class="container"> + + <div class="Page-Nav" align="center"> + <nav aria-label="Page navigation"> + <ul class="pagination pagination-sm"> + <li class="page-item"> + {% if workshoptype.has_previous %} + <a class="page-link" tabindex="-1" + href="?page={{ workshoptype.previous_page_number }}">Previous</a> + {% endif %} + </li> + <li class="page-item"> + <span class="current"> + Page {{ workshoptype.number }} of {{ workshoptype.paginator.num_pages }} + </span> + </li> + <li class="page-item"> + {% if workshoptype.has_next %} + <a class="page-link" href="?page={{ workshoptype.next_page_number }}">Next + </a> + {% endif %} + </li> + </ul> + </nav> + </div> + </div> +{% endblock %}
\ No newline at end of file diff --git a/workshop_app/templates/workshop_app/view_workshoptype_list.html b/workshop_app/templates/workshop_app/view_workshoptype_list.html new file mode 100644 index 0000000..dddd119 --- /dev/null +++ b/workshop_app/templates/workshop_app/view_workshoptype_list.html @@ -0,0 +1,114 @@ + +{% extends 'workshop_app/base.html' %} + +{% block title %} + View Workshops Type List +{% endblock %} + + +{% block header %} + <nav class="navbar navbar-default navbar-custom"> + <div class="container-fluid"> + <div class="navbar-header"> + <a class="navbar-brand" href="#">WebSiteName</a> + </div> + <ul class="nav navbar-nav"> + {% if request.user.profile.position == 'instructor'%} + <li><a href="{{ URL_ROOT }}/manage/">Manage</a></li> + <li><a href="{{ URL_ROOT }}/create_workshop/">Create Workshop</a></li> + {% else %} + <li><a href="{{ URL_ROOT }}/book/">Book</a></li> + <li><a href="{{ URL_ROOT }}/propose_workshop/">Propose a Workshop</a></li> + {% endif %} + <li class="active"><a href="{{ URL_ROOT }}/view_workshoptype_list/">View Workshop List</a></li> + <li><a href="{{ URL_ROOT }}/my_workshops/">My Workshops</a></li> + </ul> + + <ul class="nav navbar-nav navbar-right"> + <li><a href="{{ URL_ROOT }}/view_profile/"><span class="glyphicon glyphicon-user"></span> Profile </a></li> + <li><a href="{{ URL_ROOT }}/logout/"><span class="glyphicon glyphicon-log-out"></span> Logout</a></li> + </ul> + </div> + </nav> +{% endblock %} + +{% block extra %} + + <!-- <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"> --> + + <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script> + <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script> +{% endblock %} + +{% block content %} + + <div class="container"> + + <table class="table table-hover" style="border-collapse:collapse;"> + <thead> + <tr> + <th>id</th> + <th>Workshop Name</th> + <th>Workshop Duration</th> + </tr> + </thead> + + {% for w in workshoptype %} + <tbody> + <tr > + <td scope="row" id="{{ forloop.counter }}">{{ forloop.counter }}</td> + <td>{{ w.workshoptype_name }}</td> + <td>{{ w.workshoptype_duration }}</td> + <td><button class="btn btn-default btn-sm" class="accordion-toggle" data-toggle="collapse" href="#collapseOne{{ forloop.counter }}">View Workshop Details</button></td> + {% if request.user.profile.position == 'coordinator' %} + <td><button class="btn btn-default btn-sm" ><a href="{{ URL_ROOT }}/book/">Book</a></button></td> + {% endif %} + </tr> + + <tr> + <td colspan="12" class="hiddenRow"> + <div id="collapseOne{{ forloop.counter }}" class="accordion-body collapse"> + <table class="table table-striped"> + <tbody> + <tr> + <td>{{ w.workshoptype_description|safe }}</td> + </tr> + </tbody> + </table> + </div> + </td> + </tr> + </tbody> + {% endfor %} + </table> + + </div> + +<!-- Page Navigation --> + <div class="container"> + + <div class="Page-Nav" align="center"> + <nav aria-label="Page navigation"> + <ul class="pagination pagination-sm"> + <li class="page-item"> + {% if workshoptype.has_previous %} + <a class="page-link" tabindex="-1" + href="?page={{ workshoptype.previous_page_number }}">Previous</a> + {% endif %} + </li> + <li class="page-item"> + <span class="current"> + Page {{ workshoptype.number }} of {{ workshoptype.paginator.num_pages }} + </span> + </li> + <li class="page-item"> + {% if workshoptype.has_next %} + <a class="page-link" href="?page={{ workshoptype.next_page_number }}">Next + </a> + {% endif %} + </li> + </ul> + </nav> + </div> + </div> +{% endblock %}
\ No newline at end of file diff --git a/workshop_app/tests.py b/workshop_app/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/workshop_app/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/workshop_app/views.py b/workshop_app/views.py new file mode 100644 index 0000000..0557207 --- /dev/null +++ b/workshop_app/views.py @@ -0,0 +1,782 @@ +from .forms import ( + UserRegistrationForm, UserLoginForm, + ProfileForm, CreateWorkshop, + ProposeWorkshopDateForm + ) +from .models import ( + Profile, User, + has_profile, Workshop, + WorkshopType, RequestedWorkshop, + BookedWorkshop, ProposeWorkshopDate + ) +from django.template import RequestContext +from datetime import datetime, date +from django.contrib.auth import login, logout, authenticate +from django.contrib.auth.decorators import login_required +from django.contrib import messages +from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger +from django.shortcuts import render, redirect +from django.db import IntegrityError +from django.utils import timezone +from collections import OrderedDict +from dateutil.parser import parse +from .send_mails import send_email +from django.http import HttpResponse, HttpResponseRedirect +from textwrap import dedent + +__author__ = "Akshen Doke" +__credits__ = ["Mahesh Gudi", "Aditya P.", "Ankit Javalkar", + "Prathamesh Salunke", "Akshen Doke", "Kiran Kishore", + "KhushalSingh Rajput", "Prabhu Ramachandran"] + + +def is_email_checked(user): + if hasattr(user, 'profile'): + return True if user.profile.is_email_verified else False + else: + return False + + +def index(request): + '''Landing Page''' + + user = request.user + form = UserLoginForm() + if user.is_authenticated(): + if user.groups.filter(name='instructor').count() > 0: + return redirect('/manage/') + return redirect('/book/') + elif request.method == "POST": + form = UserLoginForm(request.POST) + if form.is_valid(): + user = form.cleaned_data + login(request, user) + if user.groups.filter(name='instructor').count() > 0: + return redirect('/manage/') + return redirect('/book/') + + return render(request, "workshop_app/index.html", {"form": form}) + + +def is_instructor(user): + '''Check if the user is having instructor rights''' + return True if user.groups.filter(name='instructor').count() > 0 else False + + +def user_login(request): + '''User Login''' + user = request.user + if user.is_authenticated(): + if user.groups.filter(name='instructor').count() > 0: + return redirect('/manage/') + return redirect('/book/') + + if request.method == "POST": + form = UserLoginForm(request.POST) + if form.is_valid(): + user = form.cleaned_data + login(request, user) + if user.groups.filter(name='instructor').count() > 0: + return redirect('/manage/') + return redirect('/book/') + else: + return render(request, 'workshop_app/login.html', {"form": form}) + else: + form = UserLoginForm() + return render(request, 'workshop_app/login.html', {"form": form}) + + +def user_logout(request): + '''Logout''' + logout(request) + return render(request, 'workshop_app/logout.html') + + +def activate_user(request, key): + try: + user = Profile.objects.get(activation_key=key) + except: + return redirect('/register/') + + if user.is_email_verified: + status = "Your email is already verified" + elif timezone.now() > user.key_expiry_time: + status = "Your activation has expired please register again" + Profile.objects.get(user_id=user.user_id).delete() + User.objects.get(id=user.user_id).delete() + return render(request, 'workshop_app/activation.html', + {"status": status}) + elif key == user.activation_key: + user.is_email_verified = True + user.save() + status = "Your account has been activated" + else: + logout(request) + return redirect('/logout/') + return render(request, 'workshop_app/activation.html', + {"status": status}) + + +def user_register(request): + '''User Registeration form''' + if request.method == 'POST': + form = UserRegistrationForm(request.POST) + if form.is_valid(): + data = form.cleaned_data + username, password, key = form.save() + new_user = authenticate(username=username, password=password) + login(request, new_user) + user_position = request.user.profile.position + send_email( + request, call_on='Registration', + user_position=user_position, + key=key + ) + + return render(request, 'workshop_app/activation.html') + else: + return render( + request, "workshop_app/register.html", + {"form": form} + ) + else: + form = UserRegistrationForm() + return render(request, "workshop_app/register.html", {"form": form}) + + +#This is shown to coordinator for booking workshops +def book(request): + user = request.user + if user.is_authenticated(): + if is_email_checked(user): + if user.groups.filter(name='instructor').count() > 0: + return redirect('/manage/') + + workshop_details = Workshop.objects.all() + + workshop_occurence_list = [] + + for workshops in workshop_details: + dates = workshops.recurrences.between( + datetime(2017, 3, 12, 0, 0, 0), + datetime(2040, 12, 31, 0, 0, 0), #Needs to be changed yearly + inc=True + ) + + for d in range(len(dates)): + workshop_occurence = [ + dates[d].strftime("%d-%m-%Y"), + workshops.workshop_instructor, + workshops.workshop_title, + workshops.workshop_instructor_id, + workshops.workshop_title_id, + workshops.workshop_title.workshoptype_description + ] + + workshop_occurence_list.append(workshop_occurence) + del workshop_occurence + + #Gives you the objects of BookedWorkshop + bookedworkshop = BookedWorkshop.objects.all() + if len(bookedworkshop) != 0: + for b in bookedworkshop: + ''' + handles objects from bookedworkshop + -requested + -proposed + ''' + try: + x = b.booked_workshop_requested.requested_workshop_date.strftime("%d-%m-%Y") + y = b.booked_workshop_requested.requested_workshop_title + except: + x = b.booked_workshop_proposed.proposed_workshop_date.strftime("%d-%m-%Y") + y = b.booked_workshop_proposed.proposed_workshop_title + for a in workshop_occurence_list: + if a[0] == x and a[2] == y: + workshop_occurence_list.remove(a) + del x, y + + #Objects of RequestedWorkshop for that particular coordinator + rW_obj = RequestedWorkshop.objects.filter( + requested_workshop_coordinator=request.user + ) + for r in rW_obj: + x = r.requested_workshop_date.strftime("%d-%m-%Y") + for a in workshop_occurence_list: + if a[0] == x: + workshop_occurence_list.remove(a) + del x + + + #Show upto 12 Workshops per page + paginator = Paginator(workshop_occurence_list, 12) + page = request.GET.get('page') + try: + workshop_occurences = paginator.page(page) + except PageNotAnInteger: + #If page is not an integer, deliver first page. + workshop_occurences = paginator.page(1) + except EmptyPage: + #If page is out of range(e.g 999999), deliver last page. + workshop_occurences = paginator.page(paginator.num_pages) + + return render( + request, "workshop_app/booking.html", + {"workshop_details": workshop_occurences} + ) + else: + return render(request, "workshop_app/activation.html") + else: + return redirect('/login/') + + +@login_required +def book_workshop(request): + ''' + Function for Updating RequestedWorkshop Model + ''' + if request.method == 'POST': + user_position = request.user.profile.position + client_data = request.body.decode("utf-8").split("&") + client_data = client_data[0].split("%2C") + workshop_date = client_data[0][2:] + + if client_data[-1] == '0': + queue = RequestedWorkshop.objects.filter( + requested_workshop_instructor=client_data[1], + requested_workshop_date=datetime.strptime( + client_data[0][2:], "%d-%m-%Y" + ), + requested_workshop_title=client_data[-2] + ).count() + 1 + + return HttpResponse(str(queue)) + + workshops_list = Workshop.objects.filter( + workshop_instructor=client_data[1], + workshop_title_id=client_data[2] + ) + + for workshop in workshops_list: + workshop_recurrence_list = workshop.recurrences.between( + datetime(2017, 3, 12, 0, 0, 0), + datetime(2040, 12, 31, 0, 0, 0), + inc=True + ) + + rW_obj = RequestedWorkshop() + if RequestedWorkshop.objects.filter( + requested_workshop_instructor=workshop.workshop_instructor, + requested_workshop_date=datetime.strptime( + client_data[0][2:], "%d-%m-%Y", + ), + requested_workshop_coordinator=request.user, + requested_workshop_title=client_data[-1] + ).count() > 0: + + return HttpResponse(dedent("""You already have a booking + for this workshop please check the + instructors response in My Workshops tab and + also check your email.""")) + else: + for w in workshop_recurrence_list: + if workshop_date == (w.strftime("%d-%m-%Y")): + rW_obj.requested_workshop_instructor = workshop.workshop_instructor + rW_obj.requested_workshop_coordinator = request.user + rW_obj.requested_workshop_date = datetime.strptime( + workshop_date,"%d-%m-%Y" + ) + rW_obj.requested_workshop_title = workshop.workshop_title + rW_obj.save() + + queue = RequestedWorkshop.objects.filter( + requested_workshop_instructor=workshop.workshop_instructor, + requested_workshop_date=datetime.strptime( + workshop_date, "%d-%m-%Y", + ), + requested_workshop_title=client_data[-1] + ).count() + + # Mail to instructor + send_email(request, call_on='Booking', + user_position='instructor', + workshop_date=workshop_date, + workshop_title=workshop.workshop_title.workshoptype_name, + user_name=str(request.user), + other_email=workshop.workshop_instructor.email + ) + phone_number = workshop.workshop_instructor.profile.phone_number + #Mail to coordinator + send_email(request, call_on='Booking', + workshop_date=workshop_date, + workshop_title=workshop.workshop_title.workshoptype_name, + user_name=workshop.workshop_instructor.username, + other_email=workshop.workshop_instructor.email, + phone_number=phone_number) + + return HttpResponse(dedent("""\ + Thank You, Please check + your email for further information. Your number on the + queue for this book is {0}""".format(str(queue)))) + else: + return HttpResponse("Some Error Occurred.") + + +@login_required +def manage(request): + user = request.user + if user.is_authenticated() and is_email_checked(user): + #Move user to the group via admin + if user.groups.filter(name='instructor').count() > 0: + try: + #Can Handle Multiple Workshops + workshop_details = Workshop.objects.filter( + workshop_instructor=user.id + ) + + workshop_occurence_list = [] + for workshop in workshop_details: + workshop_occurence = workshop.recurrences.between( + datetime(2017, 3, 12, 0, 0, 0), + datetime(2040, 12, 31, 0, 0, 0), + inc=True + ) + for i in range(len(workshop_occurence)): + + workshop_occurence_list.append({ + "user": str(user), + "workshop": workshop.workshop_title, + "date": workshop_occurence[i].date() + }) + + requested_workshop = RequestedWorkshop.objects.filter( + requested_workshop_instructor=user.id + ) + + + #Need to recheck logic + for j in range(len(requested_workshop)): + for i in workshop_occurence_list: + a = requested_workshop[j].requested_workshop_date + b = requested_workshop[j].requested_workshop_title + if i['date'] == a and i['workshop'] == b: + workshop_occurence_list.remove(i) + del a, b + + + #Show upto 12 Workshops per page + paginator = Paginator(workshop_occurence_list, 12) + page = request.GET.get('page') + try: + workshops = paginator.page(page) + except PageNotAnInteger: + #If page is not an integer, deliver first page. + workshops = paginator.page(1) + except EmptyPage: + #If page is out of range(e.g 999999), deliver last page. + workshops = paginator.page(paginator.num_pages) + except: + workshops = None + + return render( + request, "workshop_app/manage.html", + {"workshop_occurence_list": workshops} + ) + + return redirect('/book/') + else: + return redirect('/login/') + + +@login_required +def my_workshops(request): + user = request.user + + if user.is_authenticated() and is_email_checked(user): + if is_instructor(user): + if request.method == 'POST': + user_position = request.user.profile.position + client_data = request.body.decode("utf-8").split("&") + client_data = client_data[0].split("%2C") + + if client_data[-1] == 'ACCEPTED': + workshop_date = datetime.strptime( + client_data[1], "%Y-%m-%d" + ) + + coordinator_obj = User.objects.get(username=client_data[0][2:]) + + workshop_status = RequestedWorkshop.objects.get( + requested_workshop_instructor=user.id, + requested_workshop_date=workshop_date, + requested_workshop_coordinator=coordinator_obj.id, + requested_workshop_title=client_data[2] + ) + + workshop_status.status = client_data[-1] + workshop_status.save() + booked_workshop_obj = BookedWorkshop() + booked_workshop_obj.booked_workshop_requested = workshop_status + booked_workshop_obj.save() + + cmail = workshop_status.requested_workshop_coordinator.email + cname = workshop_status.requested_workshop_coordinator.username + cnum = workshop_status.requested_workshop_coordinator.profile.phone_number + cinstitute = workshop_status.requested_workshop_coordinator.profile.institute + inum = request.user.profile.phone_number + wtitle = workshop_status.requested_workshop_title.workshoptype_name + + #For Instructor + send_email(request, call_on='Booking Confirmed', + user_position='instructor', + workshop_date=str(client_data[1]), + workshop_title=wtitle, + user_name=str(cname), + other_email=cmail, + phone_number=cnum, + institute=cinstitute + ) + + #For Coordinator + send_email(request, call_on='Booking Confirmed', + workshop_date=str(client_data[1]), + workshop_title=wtitle, + other_email=cmail, + phone_number=inum + ) + + elif client_data[-1] == 'DELETED': + workshop_date = client_data[1] + workshops_list = Workshop.objects.filter(workshop_instructor=request.user.id, + workshop_title_id=client_data[2] + ) + + for workshop in workshops_list: + workshop_recurrence_list = workshop.recurrences.between( + datetime(2017, 3, 12, 0, 0, 0), + datetime(2040, 12, 31, 0, 0, 0), + inc=True + ) + + for d in workshop_recurrence_list: + if workshop_date == d.strftime("%Y-%m-%d"): + rW_obj = RequestedWorkshop() + rW_obj.requested_workshop_instructor = request.user + rW_obj.requested_workshop_coordinator = request.user + rW_obj.requested_workshop_date = workshop_date + rW_obj.requested_workshop_title = workshop.workshop_title + rW_obj.status = client_data[-1] + rW_obj.save() + bW_obj = BookedWorkshop() + bW_obj.booked_workshop_requested = rW_obj + bW_obj.save() + + #For instructor + send_email(request, call_on='Workshop Deleted', + workshop_date=str(client_data[1]), + workshop_title=workshop.workshop_title + ) + + return HttpResponse("Workshop Deleted") + + elif client_data[-1] == 'APPROVED': + print(client_data) + workshop_date = datetime.strptime( + client_data[1], "%Y-%m-%d" + ) + + coordinator_obj = User.objects.get(username=client_data[0][2:]) + workshop_status = ProposeWorkshopDate.objects.get( + proposed_workshop_date=workshop_date, + proposed_workshop_coordinator=coordinator_obj.id, + proposed_workshop_title=client_data[2] + ) + + workshop_status.status = 'ACCEPTED' + workshop_status.proposed_workshop_instructor = user + workshop_status.save() + booked_workshop_obj = BookedWorkshop() + booked_workshop_obj.booked_workshop_proposed = workshop_status + booked_workshop_obj.save() + + cmail = workshop_status.proposed_workshop_coordinator.email + cname = workshop_status.proposed_workshop_coordinator.username + cnum = workshop_status.proposed_workshop_coordinator.profile.phone_number + cinstitute = workshop_status.proposed_workshop_coordinator.profile.institute + inum = request.user.profile.phone_number + wtitle = workshop_status.proposed_workshop_title.workshoptype_name + + #For Instructor + send_email(request, call_on='Booking Confirmed', + user_position='instructor', + workshop_date=str(client_data[1]), + workshop_title=wtitle, + user_name=str(cname), + other_email=cmail, + phone_number=cnum, + institute=cinstitute + ) + + #For Coordinator + send_email(request, call_on='Booking Confirmed', + workshop_date=str(client_data[1]), + workshop_title=wtitle, + other_email=cmail, + phone_number=inum + ) + + else: + workshop_date = datetime.strptime( + client_data[1], "%Y-%m-%d" + ) + coordinator_obj = User.objects.get(username=client_data[0][2:]) + workshop_status = RequestedWorkshop.objects.get( + requested_workshop_instructor=user.id, + requested_workshop_date=workshop_date, + requested_workshop_coordinator=coordinator_obj.id, + requested_workshop_title=client_data[2] + ) + workshop_status.status = client_data[-1] + workshop_status.save() + + wtitle = workshop_status.requested_workshop_title.workshoptype_name + cmail = workshop_status.requested_workshop_coordinator.email + cname = workshop_status.requested_workshop_coordinator.username + cnum = workshop_status.requested_workshop_coordinator.profile.phone_number + cinstitute = workshop_status.requested_workshop_coordinator.profile.institute + + #For Instructor + send_email(request, call_on='Booking Request Rejected', + user_position='instructor', + workshop_date=str(client_data[1]), + workshop_title=wtitle, + user_name=str(cname), + other_email=cmail, + phone_number=cnum, + institute=cinstitute + ) + + #For Coordinator + send_email(request, call_on='Booking Request Rejected', + workshop_date=str(client_data[1]), + workshop_title=wtitle, + other_email=cmail + ) + + workshops = [] + workshop_occurence_list = RequestedWorkshop.objects.filter( + requested_workshop_instructor=user.id + ) + for w in workshop_occurence_list: + workshops.append(w) + + proposed_workshop = ProposeWorkshopDate.objects.filter( + proposed_workshop_instructor=user.id + ) + for p in proposed_workshop: + workshops.append(p) + + proposed_workshop_pending = ProposeWorkshopDate.objects.filter( + status='Pending' + ) + for p in proposed_workshop_pending: + workshops.append(p) + + #Show upto 12 Workshops per page + paginator = Paginator(workshops, 12) + page = request.GET.get('page') + try: + workshop_occurences = paginator.page(page) + except PageNotAnInteger: + #If page is not an integer, deliver first page. + workshop_occurences = paginator.page(1) + except EmptyPage: + #If page is out of range(e.g 999999), deliver last page. + workshop_occurences = paginator.page(paginator.num_pages) + return render(request, 'workshop_app/my_workshops.html', + { "workshop_occurences" :workshop_occurences}) + + else: + workshops = [] + workshop_occurence_list = RequestedWorkshop.objects.filter( + requested_workshop_coordinator=user.id + ) + for w in workshop_occurence_list: + workshops.append(w) + + proposed_workshop = ProposeWorkshopDate.objects.filter( + proposed_workshop_coordinator=user.id + ) + for p in proposed_workshop: + workshops.append(p) + + #Show upto 12 Workshops per page + paginator = Paginator(workshops, 12) + page = request.GET.get('page') + try: + workshop_occurences = paginator.page(page) + except PageNotAnInteger: + #If page is not an integer, deliver first page. + workshop_occurences = paginator.page(1) + except EmptyPage: + #If page is out of range(e.g 999999), deliver last page. + workshop_occurences = paginator.page(paginator.num_pages) + return render(request, 'workshop_app/my_workshops.html', + {"workshop_occurences": workshop_occurences}) + else: + return redirect('/login/') + + +@login_required +def propose_workshop(request): + '''Coordinator proposed a workshop and date''' + + user = request.user + if is_email_checked(user): + if is_instructor(user): + return redirect('/manage/') + else: + if request.method == 'POST': + form = ProposeWorkshopDateForm(request.POST) + if form.is_valid(): + form_data = form.save(commit=False) + form_data.proposed_workshop_coordinator = user + form_data.proposed_workshop_coordinator.save() + form_data.save() + return redirect('/my_workshops/') + else: + form = ProposeWorkshopDateForm() + return render( + request, 'workshop_app/propose_workshop.html', + {"form": form } + ) + else: + return render(request, 'workshop_app/activation.html') + +@login_required +def view_profile(request): + """ view instructor and coordinator profile """ + return render(request, "workshop_app/view_profile.html") + + +@login_required +def edit_profile(request): + """ edit profile details facility for instructor and coordinator """ + + user = request.user + if is_instructor(user) and is_email_checked(user): + template = 'workshop_app/manage.html' + else: + if is_email_checked(user): + template = 'workshop_app/booking.html' + context = {'template': template} + if has_profile(user) and is_email_checked(user): + profile = Profile.objects.get(user_id=user.id) + else: + profile = None + + if request.method == 'POST': + form = ProfileForm(request.POST, user=user, instance=profile) + if form.is_valid(): + form_data = form.save(commit=False) + form_data.user = user + form_data.user.first_name = request.POST['first_name'] + form_data.user.last_name = request.POST['last_name'] + form_data.user.save() + form_data.save() + + return render( + request, 'workshop_app/profile_updated.html', + context + ) + else: + context['form'] = form + return render(request, 'workshop_app/edit_profile.html', context) + else: + form = ProfileForm(user=user, instance=profile) + context['form'] = form + return render(request, 'workshop_app/edit_profile.html', context) + + +@login_required +def create_workshop(request): + '''Instructor creates workshops''' + + user = request.user + if is_instructor(user) and is_email_checked(user): + if request.method == 'POST': + form = CreateWorkshop(request.POST) + if form.is_valid(): + form_data = form.save(commit=False) + #form_data.profile_id = profile.id + form_data.workshop_instructor = user + form_data.workshop_instructor.save() + form_data.save() + return redirect('/manage/') + else: + form = CreateWorkshop() + return render( + request, 'workshop_app/create_workshop.html', + {"form": form } + ) + else: + return redirect('/book/') + + +@login_required +def view_workshoptype_list(request): + '''Gives the types of workshop details ''' + user = request.user + if is_email_checked(user): + workshoptype_list = WorkshopType.objects.all() + + paginator = Paginator(workshoptype_list, 12) #Show upto 12 workshops per page + + page = request.GET.get('page') + try: + workshoptype = paginator.page(page) + except PageNotAnInteger: + #If page is not an integer, deliver first page. + workshoptype = paginator.page(1) + except EmptyPage: + #If page is out of range(e.g 999999), deliver last page. + workshoptype = paginator.page(paginator.num_pages) + + return render( + request, 'workshop_app/view_workshoptype_list.html', \ + {'workshoptype': workshoptype} + ) + else: + return redirect('/activate_user/') + + +def view_workshoptype_details(request): + '''Gives the details for types of workshops.''' + workshoptype_list = WorkshopType.objects.all() + + paginator = Paginator(workshoptype_list, 12) #Show upto 12 workshops per page + + page = request.GET.get('page') + try: + workshoptype = paginator.page(page) + except PageNotAnInteger: + #If page is not an integer, deliver first page. + workshoptype = paginator.page(1) + except EmptyPage: + #If page is out of range(e.g 999999), deliver last page. + workshoptype = paginator.page(paginator.num_pages) + + return render( + request, 'workshop_app/view_workshoptype_details.html', \ + {'workshoptype': workshoptype} + ) + + +def benefits(request): + return render(request, 'workshop_app/view_benefits.html') + +def faq(request): + return render(request, 'workshop_app/view_faq.html') + +def how_to_participate(request): + return render(request, 'workshop_app/how_to_participate.html')
\ No newline at end of file |