From e22ae60e925a7a63c7d65a5102d34821904685f4 Mon Sep 17 00:00:00 2001 From: andrewlalis Date: Tue, 2 Oct 2018 11:56:04 +0200 Subject: [PATCH 01/31] Added template system. --- backend/RateMyCourse/urls.py | 9 ++++++- backend/db.sqlite3 | Bin 71680 -> 72704 bytes .../postings/collections/collection.html | 16 ++++++++++++ .../postings/collections/courses.html | 12 +++++++++ .../postings/collections/universities.html | 7 ++++++ .../templates/postings/generic_page.html | 23 ++++++++++++++++++ .../postings/templates/postings/index.html | 17 +++++++++++++ backend/postings/views.py | 16 ++++++++++++ 8 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 backend/postings/templates/postings/collections/collection.html create mode 100644 backend/postings/templates/postings/collections/courses.html create mode 100644 backend/postings/templates/postings/collections/universities.html create mode 100644 backend/postings/templates/postings/generic_page.html create mode 100644 backend/postings/templates/postings/index.html diff --git a/backend/RateMyCourse/urls.py b/backend/RateMyCourse/urls.py index 9cbc84d..dae6471 100644 --- a/backend/RateMyCourse/urls.py +++ b/backend/RateMyCourse/urls.py @@ -18,10 +18,17 @@ from django.urls import re_path,path,include from django.conf.urls import url from django.contrib.staticfiles.views import serve from django.views.generic import RedirectView +from postings import views urlpatterns = [ # / routes to index.html - url(r'^$', serve, kwargs={'path': 'index.html'}), + path('', views.index, name='homepage'), + + # /universities routes to a list of universities. + path('universities', views.universities, name='universities_list'), + + # /courses routes to a list of courses. + path('courses', views.courses, name='courses_list'), # static files (*.css, *.js, *.jpg etc.) served on / # (assuming Django uses /static/ and /media/ for static/media urls) diff --git a/backend/db.sqlite3 b/backend/db.sqlite3 index 359edf330bb4fdc20cdd32a017fd03ced1c164be..e236f72ab9b8af8039458c850c6f5fdbc2b290f1 100644 GIT binary patch delta 1810 zcmZ{kZD<@-6o&8IcV<76O|pbUn$Qesg;kU7%BlirB6|MeaogXC8Yq@f7$viV?+H#k1{q7o_B1pzKdy+(X>vEGui5&4fzR*>^P0j3m}E}lXcZ9@qFidY zRCB4~65&$GrGiVCOQ<|Q-V%}6-U?XZ9o31I8R6|E&{*W^YqghTaUw#VChRk8w9rNR z9xc#=!d>Bt&?kh*r=-M!-qjTelC~=S86gZgQCbmqTFNo1X|s;S7rU^ivAK*_W$2139B!QXg@ z1(x(3>U|IiH}g^NNhN_jgVOY@CfSOI7Umw mlS($7Q1&W!%Yb)OaZ=mPlK5GnYVm9~t7Y}nwu(|aD*7LXp0l3- delta 264 zcmZqJ!P2mSWr8%X7Xt%>8xU&%G2=uHb4IU?2}{^T*qI#}m>rp4F-I^jWuDGl$b6bv ze6t{nCi7%R?n)*GhRJ)l^~6M&nROXcvJ&&s^Wzg!ax?SdbMn(UH}SC8Y-UOL%e|Q~ zgjq$5llck*^B?B#%%7OwGQVJc%zTgeCi4}bS-Y4wU#T`=!KYv{P=OdH;{pce4a|AW zI!v#aRxqV8sW3ibTmUqnjdAmWxd}{*Iz%=LD!gZ&tiU3;NrjPPGvf+omc=YK9E(|0 gfOrp(4Wdu5Y-aKK$G(~A3KNhO^Ot`! + {% for entity in entities %} +
  • + {% block entity %} + {% endblock %} +
  • + {% endfor %} + + +{% endblock %} \ No newline at end of file diff --git a/backend/postings/templates/postings/collections/courses.html b/backend/postings/templates/postings/collections/courses.html new file mode 100644 index 0000000..4805231 --- /dev/null +++ b/backend/postings/templates/postings/collections/courses.html @@ -0,0 +1,12 @@ +{% extends "postings/collections/collection.html" %} + +{# Represents a list of university entities. #} + +{% block entity %} + {{ entity.name }}, University: {{ entity.taught_at_university.name}}
    +
      + {% for professor in entity.professors.all %} +
    • {{ professor.name }}
    • + {% endfor %} +
    +{% endblock %} \ No newline at end of file diff --git a/backend/postings/templates/postings/collections/universities.html b/backend/postings/templates/postings/collections/universities.html new file mode 100644 index 0000000..6f392e1 --- /dev/null +++ b/backend/postings/templates/postings/collections/universities.html @@ -0,0 +1,7 @@ +{% extends "postings/collections/collection.html" %} + +{# Represents a list of university entities. #} + +{% block entity %} + {{ entity.name }} +{% endblock %} \ No newline at end of file diff --git a/backend/postings/templates/postings/generic_page.html b/backend/postings/templates/postings/generic_page.html new file mode 100644 index 0000000..9f8d23a --- /dev/null +++ b/backend/postings/templates/postings/generic_page.html @@ -0,0 +1,23 @@ +{# This page represents the base template that all others will extend from. #} +{# It will contain a universal navigation bar, script tags, footers, and other things needed on every page. #} + + + + + + {% block title %}RateMyCourse{% endblock %} + + + + +
    +

    RateMyCourse

    +
    + + {# All of a page's content to display should be placed in here. #} +
    + {% block content %} + {% endblock %} +
    + + \ No newline at end of file diff --git a/backend/postings/templates/postings/index.html b/backend/postings/templates/postings/index.html new file mode 100644 index 0000000..d26bf17 --- /dev/null +++ b/backend/postings/templates/postings/index.html @@ -0,0 +1,17 @@ +{% extends "postings/generic_page.html" %} + +{# The homepage for the website. #} + +{% block content %} +

    + Click one of the links below to view a list of all those entities. +

    + +{% endblock %} \ No newline at end of file diff --git a/backend/postings/views.py b/backend/postings/views.py index 91ea44a..19b0baa 100644 --- a/backend/postings/views.py +++ b/backend/postings/views.py @@ -1,3 +1,19 @@ from django.shortcuts import render +from django.http import HttpResponse +from postings.models import * # Create your views here. + +# The view for the homepage, or index.html +def index(request): + return render(request, 'postings/index.html') + +def universities(request): + universities_list = University.objects.all() + context = {'entities': universities_list} + return render(request, 'postings/collections/universities.html', context) + +def courses(request): + courses_list = Course.objects.all() + context = {'entities': courses_list} + return render(request, 'postings/collections/courses.html', context) \ No newline at end of file -- 2.34.1 From 714f3241ceb291625d8003248c82cc8b448c3392 Mon Sep 17 00:00:00 2001 From: andrewlalis Date: Tue, 2 Oct 2018 14:06:53 +0200 Subject: [PATCH 02/31] Added templates for all basic things. --- backend/RateMyCourse/urls.py | 6 +++++ backend/db.sqlite3 | Bin 72704 -> 72704 bytes .../postings/collections/collection.html | 4 +++ .../postings/collections/courses.html | 11 ++++---- .../postings/collections/universities.html | 6 ++++- .../postings/entity_pages/course.html | 11 ++++++++ .../postings/entity_pages/entity.html | 24 ++++++++++++++++++ .../postings/entity_pages/university.html | 16 ++++++++++++ .../templates/postings/generic_page.html | 6 ++--- backend/postings/views.py | 22 ++++++++++++++-- 10 files changed, 94 insertions(+), 12 deletions(-) create mode 100644 backend/postings/templates/postings/entity_pages/course.html create mode 100644 backend/postings/templates/postings/entity_pages/entity.html create mode 100644 backend/postings/templates/postings/entity_pages/university.html diff --git a/backend/RateMyCourse/urls.py b/backend/RateMyCourse/urls.py index dae6471..cc3e5cb 100644 --- a/backend/RateMyCourse/urls.py +++ b/backend/RateMyCourse/urls.py @@ -27,9 +27,15 @@ urlpatterns = [ # /universities routes to a list of universities. path('universities', views.universities, name='universities_list'), + # /universities/ routes to a specific university. + path('universities/', views.university_entity, name='university entity'), + # /courses routes to a list of courses. path('courses', views.courses, name='courses_list'), + # /courses/ routes to a specific course. + path('courses/', views.course_entity, name='course entity'), + # static files (*.css, *.js, *.jpg etc.) served on / # (assuming Django uses /static/ and /media/ for static/media urls) url(r'^(?!/?static/)(?!/?media/)(?P.*\..*)$', diff --git a/backend/db.sqlite3 b/backend/db.sqlite3 index e236f72ab9b8af8039458c850c6f5fdbc2b290f1..a1acc0e128e208b3cdb393328e9c388717793535 100644 GIT binary patch delta 490 zcmZqJ!P2mUWr8$g$V3@u#*mE(i`bS6P6ZWwq~4cds=+51Gk|X^DYJ<1{5H~%dE{=kY8MqnU`K1UzA#wnOeSi zI(Kf4gfR0A2IfD^-G{FwP3^G)U}%riDiRn#y~{&1ONFN+Vdh1X z*&9@um=^)RmXuT~ zr03_SC?w}378i$PWELv`QC4Yji9(`6abj*kPO1XLJql_0MG7SusSuS4L8*nMnMJ9& zsd**E3aNSNnR%(HML_54DR?TR98f0RxYb`8Nae@6Cb=@0r;d7+9DY zIoUStU`gO(WvXIe-pQQLtig1UsS4=n3??;KVNM1|etm65PEPEm8XH&|7*2jLUxAT% K`#~v2dqx1KD~8el delta 204 zcmZqJ!P2mUWr8$g@I)DB#^8+!i`b=F8Mv5EGB7(b^D##-FJ+$2T*!QyS%v8&)4R=r zENhu2pX7>S6OtBSwq~4cds=+51Gk}?5HGVfM?rpZNoHPpaePr~S!QZE^DYJ<1~_28 z$RMG{FwP3^G)U}n`J6$m?s8sO#X10W%HuyBo<~N z=H-*w8&rXIRx@v2-W;p5m_>nOG0Tnw9u}s949q*3^O-f64g#e&GHpL7#c0n60G*CK A00000 diff --git a/backend/postings/templates/postings/collections/collection.html b/backend/postings/templates/postings/collections/collection.html index 37d3f2d..90d7f3b 100644 --- a/backend/postings/templates/postings/collections/collection.html +++ b/backend/postings/templates/postings/collections/collection.html @@ -4,10 +4,14 @@ {% block content %} +{% block collection_name %} +{% endblock %} +
      {% for entity in entities %}
    • {% block entity %} + {{ entity.name }} {% endblock %}
    • {% endfor %} diff --git a/backend/postings/templates/postings/collections/courses.html b/backend/postings/templates/postings/collections/courses.html index 4805231..0fc63cb 100644 --- a/backend/postings/templates/postings/collections/courses.html +++ b/backend/postings/templates/postings/collections/courses.html @@ -2,11 +2,10 @@ {# Represents a list of university entities. #} +{% block collection_name %} +

      Courses

      +{% endblock %} + {% block entity %} - {{ entity.name }}, University: {{ entity.taught_at_university.name}}
      -
        - {% for professor in entity.professors.all %} -
      • {{ professor.name }}
      • - {% endfor %} -
      +

      {{ entity.name }}

      {% endblock %} \ No newline at end of file diff --git a/backend/postings/templates/postings/collections/universities.html b/backend/postings/templates/postings/collections/universities.html index 6f392e1..bb5374d 100644 --- a/backend/postings/templates/postings/collections/universities.html +++ b/backend/postings/templates/postings/collections/universities.html @@ -2,6 +2,10 @@ {# Represents a list of university entities. #} +{% block collection_name %} +

      Universities

      +{% endblock %} + {% block entity %} - {{ entity.name }} +

      {{ entity.name }}

      {% endblock %} \ No newline at end of file diff --git a/backend/postings/templates/postings/entity_pages/course.html b/backend/postings/templates/postings/entity_pages/course.html new file mode 100644 index 0000000..8508196 --- /dev/null +++ b/backend/postings/templates/postings/entity_pages/course.html @@ -0,0 +1,11 @@ +{% extends "postings/entity_pages/entity.html" %} + +{% block entity_info %} + Taught at: {{ entity.taught_at_university.name }} +

      Professors

      +
        + {% for professor in entity.professors.all %} +
      • {{ professor.name }}
      • + {% endfor %} +
      +{% endblock %} \ No newline at end of file diff --git a/backend/postings/templates/postings/entity_pages/entity.html b/backend/postings/templates/postings/entity_pages/entity.html new file mode 100644 index 0000000..b066368 --- /dev/null +++ b/backend/postings/templates/postings/entity_pages/entity.html @@ -0,0 +1,24 @@ +{% extends "postings/generic_page.html" %} + +{# Represents a single entity's detail page. #} + +{% block content %} + +

      Name: {{ entity.name }}

      + +{% block entity_info %} +{% endblock %} + +
      +

      Reviews

      +
        + {% for review in entity.review_set.all %} +
      • +

        {{ review.title }}

        {{ review.rating }} +

        {{ review.content }} +

      • + {% endfor %} +
      +
      + +{% endblock %} \ No newline at end of file diff --git a/backend/postings/templates/postings/entity_pages/university.html b/backend/postings/templates/postings/entity_pages/university.html new file mode 100644 index 0000000..0ea0b8c --- /dev/null +++ b/backend/postings/templates/postings/entity_pages/university.html @@ -0,0 +1,16 @@ +{% extends "postings/entity_pages/entity.html" %} + +{% block entity_info %} +

      Courses

      + +

      Professors

      +
        + {% for professor in entity.professor_set.all %} +
      • {{ professor.name }}
      • + {% endfor %} +
      +{% endblock %} \ No newline at end of file diff --git a/backend/postings/templates/postings/generic_page.html b/backend/postings/templates/postings/generic_page.html index 9f8d23a..f49084f 100644 --- a/backend/postings/templates/postings/generic_page.html +++ b/backend/postings/templates/postings/generic_page.html @@ -10,9 +10,9 @@ -
      -

      RateMyCourse

      -
      +
      +

      RateMyCourse

      +
      {# All of a page's content to display should be placed in here. #}
      diff --git a/backend/postings/views.py b/backend/postings/views.py index 19b0baa..58288a1 100644 --- a/backend/postings/views.py +++ b/backend/postings/views.py @@ -1,5 +1,5 @@ from django.shortcuts import render -from django.http import HttpResponse +from django.http import HttpResponse, Http404 from postings.models import * # Create your views here. @@ -8,12 +8,30 @@ from postings.models import * def index(request): return render(request, 'postings/index.html') +# The view for a listing of universities. def universities(request): universities_list = University.objects.all() context = {'entities': universities_list} return render(request, 'postings/collections/universities.html', context) +# The view for /universities/ Displays one university entity. +def university_entity(request, university_id): + try: + university = University.objects.get(pk=university_id) + except University.DoesNotExist: + raise Http404("University does not exist") + return render(request, 'postings/entity_pages/university.html', {'entity': university}) + +# The view for a listing of courses. def courses(request): courses_list = Course.objects.all() context = {'entities': courses_list} - return render(request, 'postings/collections/courses.html', context) \ No newline at end of file + return render(request, 'postings/collections/courses.html', context) + +# The view for a specific course entity. +def course_entity(request, course_id): + try: + course = Course.objects.get(pk=course_id) + except Course.DoesNotExist: + raise Http404("Course does not exist") + return render(request, 'postings/entity_pages/course.html', {'entity': course}) \ No newline at end of file -- 2.34.1 From ed92b5d3e189cdc634048e1ba7b4cd6a31d11dcd Mon Sep 17 00:00:00 2001 From: andrewlalis Date: Tue, 2 Oct 2018 14:48:26 +0200 Subject: [PATCH 03/31] Added basic search function. --- backend/RateMyCourse/urls.py | 3 ++ .../postings/templates/postings/index.html | 30 +++++++++++++------ backend/postings/views.py | 8 ++++- 3 files changed, 31 insertions(+), 10 deletions(-) diff --git a/backend/RateMyCourse/urls.py b/backend/RateMyCourse/urls.py index cc3e5cb..581fd0f 100644 --- a/backend/RateMyCourse/urls.py +++ b/backend/RateMyCourse/urls.py @@ -24,6 +24,9 @@ urlpatterns = [ # / routes to index.html path('', views.index, name='homepage'), + # /?search_query=xxx routes to the homepage, with displaying some basic results. + path(' - Click one of the links below to view a list of all those entities. -

      -
        -
      • + {# First section for searching our database. #} +
        +
        + + +
        +
      • -
      • Courses -
      • -
      + + + + {# Second section for displaying results, or whatever should be shown first. #} + {% if results %} +
      +
        + {% for entity in results %} +
      • {{ entity.name }}
      • + {% endfor %} +
      +
      + {% endif %} + {% endblock %} \ No newline at end of file diff --git a/backend/postings/views.py b/backend/postings/views.py index 58288a1..61c25b9 100644 --- a/backend/postings/views.py +++ b/backend/postings/views.py @@ -5,8 +5,14 @@ from postings.models import * # Create your views here. # The view for the homepage, or index.html +# There is an optional 'search_query GET parameter, which, if provided, gives the template a 'results' variable. def index(request): - return render(request, 'postings/index.html') + search_query = request.GET.get('search_query', None) + results = None + if search_query: + results = RateableEntity.objects.filter(name__icontains=search_query) + + return render(request, 'postings/index.html', {'results': results}) # The view for a listing of universities. def universities(request): -- 2.34.1 From aff615c3e5c4cc12b1cbf4c0a8202681c2fc278d Mon Sep 17 00:00:00 2001 From: andrewlalis Date: Tue, 2 Oct 2018 15:24:59 +0200 Subject: [PATCH 04/31] Compiled migrations into just first migration. --- backend/db.sqlite3 | Bin 71680 -> 72704 bytes backend/postings/migrations/0001_initial.py | 21 +++++++++++-- .../migrations/0002_auto_20180927_1115.py | 18 ----------- backend/postings/models.py | 28 +++++++++++++++++- 4 files changed, 46 insertions(+), 21 deletions(-) delete mode 100644 backend/postings/migrations/0002_auto_20180927_1115.py diff --git a/backend/db.sqlite3 b/backend/db.sqlite3 index 359edf330bb4fdc20cdd32a017fd03ced1c164be..232a12ee572ac15d3ed89ffc49a0d6fdbbc3551b 100644 GIT binary patch delta 1646 zcmZ8hdrVVT7(d_nZfOhc)mFMIg+k>qh4ScQr3EIgx}kGUVIaQ7YK0E!c(>}@mQ5fr z`$HpmP!@In7?-Im8*()m9U2p(fYE72VbdAS+%kqP)3_{4Hp5PfbHi}7##6Yt?K_#-~RoA@1G z!C^d)-{M(3CF=wmn%!Q`b5?P%S8~X!;4rt0L*^O|&o7m4Vycj+)?xxt(MJT+a1u9S z7<;e-3+W^Jh`YH%6~>uZq+;_gNdm4Wv8*UADaMc_;sO=B8kblC)$DI= z2n2(HrbaiLj58*SbeLc$rYI1T;c0XEx<1Q>ZhC?# zUk<3~MS6~&rYAUiKAo*V0MQ*qR}}N3=#(#)H~?a0STeO3v@-mp5H#I{R?s<62Nu%J zbV9p){MVhpuIzEhsoh^dyq33sQazy)R1aD7HWxqb@+7m5CzE)r^MGyTr7UN^6|!09 zgv1ihq_I!-*TuFQURO#U4|F)$)x+_usyB{R?KMJ1l(cK_;K2jJ?x6u#!%hyZhkVvK zE-~w{U%gr-wV7Un_HuT1$j+_~7eW^63!B)QF^Mf0X@OPj*hm(<5cQHf7{hu8jXYef z{NAPQ!oe3+{MBo5E!4XbD)Oq3$0ogL1a8w;X0YmScE| z$?RHh9(JhSV8e&AAop>qF>GMMDVH1(0lw$`3HKiltDusNef<(RA{04y&-Elp46t2JX|$){o~wk=!}n94S4Y zP|y*&g@Y0QBI!KgDQvIyva*R{u*jVg8K8dgEpBd^HaD>Kck`fxb>3|j_@5o&{0sd* z2pUwwX{NllLN*J2kWc?sLKCo(sG)_Ro_<5yX(2qoz378u(878vs&$5o5SXa2st)uj@53qISTELLR&$u(_P?l6%@y_)ekcb&*&Tl zR=dkBSKjl37B7)Fo@3;3%wm@xCdWTRwmY280=DO2exwv9FU7VyTOlj{n36CZoIOen zcvKL8RqzT#v_CJJAwUX@<(@E(>v95d{|8H11GB#j7{rxYa)^y#4#`qM$s!W5z87C|+K zTfE|HvF)a6rQ~oxhmWn>XMr4kUgxmG``WD8=G6M8YF~(tv{dtEUn?)Ub)MaspJ`sc zqQbm<<+5d*vBke37>Kl{wVvJnP!clv{FimJl`x|%1ADPCiwMPP7 t^g<*ZHL%&PT-Ik4g@{kK^GI$AAG?9j*68F-H3u7f_4R?q(35DH{{m3I?Mnav delta 1206 zcmY*YdrVtp6#ve5F7^^AwdHXKSnLqgmRC#5t2|0!bQ2Z?VMI*`!%+bvkI_ztBN;^( z7enIoY+%qR)W=^WW4&f8YC=pVi!oa$Ok-fhL`|09%p@BB+5Yfr9WmaU^E)};Ip=rI z{mwm;VQF$nI+v|)W{i1+JShZ(biY$*FKA{(yWs?3X>mm$tHyiyH{QY9_%rTe6o14G zyn)~1Ra{Z^QYB`W$0+O#0<10p1+@a6a0+<5T#aI`l$oN%GfabShHl)!XYo^<#pC!L zDk9&E^jK2HX}ywwcIbPlcesC~=h(=w-#hH@@sE#swFWH~$fF}Z|KM=HuV>8r%AogE z{DK(-|APl3%#fUnk0$n>@DKEy@Oj5lAHo8NTch5wp+TQ-aAepaqV;rji2pq2lD?dZj8sN#8?z+d>5=y;i{TPbD`ftyTR$ts4B@D%o8 z8`fe8W@9qH%Qr<}n5&xxiwzz8I%y6Jij!`xUiaAH-3dvR4&6T(8sL%%n8b1!%Y_?w zm^--Te=Q0_?VMQz+CO8LgkdMWRDx6K<@DQJJ?N?M{hPXg&7o1Mt06G%?|tEA?`%mn zC~<&P;ompglMUTEvsPqt-p}^F7h7d)6h0x5 zfI8uDVxXv&io+f#rgIw#O^4f|hPJ~UkRP`vmi6@fazm&_l2z%ehzu_J;c7kD=vL53 zYimiW>zn;Crry&mRRxoWi=`O?1mjz}OGv?W?G6E z>A7`OP;3BzEql}9Z38F+kjjoqL*@NR5|Lak=1)BYT6$q^fA9*3s2kEu#7I2CNa%g7TMAA>Cn%J0ASQlyTJgx5TdO`j2cMp#p zB6cycax>T^W`78Iou1TPbDFiPsI7`SgCkb_$!&^f6Iiv|S1fK~E{sZ;sVz~eS diff --git a/backend/postings/migrations/0001_initial.py b/backend/postings/migrations/0001_initial.py index f7cab3a..ce37acb 100644 --- a/backend/postings/migrations/0001_initial.py +++ b/backend/postings/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 2.1.1 on 2018-09-27 09:48 +# Generated by Django 2.1.1 on 2018-10-02 13:24 from django.db import migrations, models import django.db.models.deletion @@ -17,6 +17,8 @@ class Migration(migrations.Migration): fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name', models.CharField(max_length=256)), + ('created_date', models.DateTimeField(auto_now_add=True)), + ('entity_type', models.SmallIntegerField(choices=[(0, 'University'), (1, 'Course'), (2, 'Professor')])), ], ), migrations.CreateModel( @@ -46,10 +48,18 @@ class Migration(migrations.Migration): ('username', models.CharField(max_length=200)), ('rating', models.IntegerField(default=1)), ('title', models.CharField(max_length=200)), - ('date_published', models.DateField(verbose_name='date published')), + ('date_published', models.DateTimeField(auto_now_add=True)), ('content', models.CharField(max_length=200)), ], ), + migrations.CreateModel( + name='User', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=64)), + ('birth_date', models.DateField()), + ], + ), migrations.CreateModel( name='Course', fields=[ @@ -68,9 +78,16 @@ class Migration(migrations.Migration): name='University', fields=[ ('rateableentity_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='postings.RateableEntity')), + ('website_url', models.URLField()), + ('location', models.CharField(max_length=256)), ], bases=('postings.rateableentity',), ), + migrations.AddField( + model_name='review', + name='author', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='postings.User'), + ), migrations.AddField( model_name='review', name='rateable_entity', diff --git a/backend/postings/migrations/0002_auto_20180927_1115.py b/backend/postings/migrations/0002_auto_20180927_1115.py deleted file mode 100644 index 68acb33..0000000 --- a/backend/postings/migrations/0002_auto_20180927_1115.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.1.1 on 2018-09-27 11:15 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('postings', '0001_initial'), - ] - - operations = [ - migrations.AlterField( - model_name='universityreview', - name='date_published', - field=models.DateTimeField(auto_now_add=True), - ), - ] diff --git a/backend/postings/models.py b/backend/postings/models.py index f6cf652..70049a5 100644 --- a/backend/postings/models.py +++ b/backend/postings/models.py @@ -1,9 +1,30 @@ from django.db import models +# Represents an authenticated reviewer or reader of reviews. +class User(models.Model): + # A non-unique name for the user. + name = models.CharField(max_length=64) + # The user's birth date. + birth_date = models.DateField() + # Represents any object for which reviews can be made. (Universities, Professors, etc.) class RateableEntity(models.Model): + # Constants defined for types of rateable entities. + UNIVERSITY = 0 + COURSE = 1 + PROFESSOR = 2 + TYPE_CHOICES = ( + (UNIVERSITY, 'University'), + (COURSE, 'Course'), + (PROFESSOR, 'Professor') + ) + # The human-readable name of this entity. name = models.CharField(max_length=256) + # The date and time at which this entity was created. + created_date = models.DateTimeField(auto_now_add=True) + # The type of entity this is. + entity_type = models.SmallIntegerField(choices=TYPE_CHOICES) # A review represents any single data entry to the database. class Review(models.Model): @@ -19,6 +40,8 @@ class Review(models.Model): created_date = models.DateTimeField(auto_now_add=True) # The date and time at which the last modification to this review was published. last_updated_date = models.DateTimeField(auto_now=True) + # A reference to the person who created this review. + author = models.ForeignKey('postings.User', on_delete=models.PROTECT) # A vote for a review as either positive or negative. class ReviewHelpfulVote(models.Model): @@ -30,7 +53,10 @@ class ReviewHelpfulVote(models.Model): # A RateableEntity for universities. class University(RateableEntity): - pass + # A string referring to the URL of the university. Every single university should have one. + website_url = models.URLField() + # A string referring to the location of the university. + location = models.CharField(max_length=256) # A RateableEntity for professors, who belong to one or more university. class Professor(RateableEntity): -- 2.34.1 From 8a9c51e856b4fc87dd595bd3bf7066c6ba341ccc Mon Sep 17 00:00:00 2001 From: andrewlalis Date: Tue, 2 Oct 2018 16:27:29 +0200 Subject: [PATCH 05/31] Added average rating. --- backend/db.sqlite3 | Bin 73728 -> 77824 bytes backend/postings/admin.py | 3 +- .../migrations/0002_auto_20181002_1338.py | 19 ++++++++++++ .../migrations/0003_auto_20181002_1355.py | 25 +++++++++++++++ backend/postings/models.py | 29 ++++++++++++++++-- .../postings/entity_pages/entity.html | 2 +- backend/postings/views.py | 1 + 7 files changed, 75 insertions(+), 4 deletions(-) create mode 100644 backend/postings/migrations/0002_auto_20181002_1338.py create mode 100644 backend/postings/migrations/0003_auto_20181002_1355.py diff --git a/backend/db.sqlite3 b/backend/db.sqlite3 index facb5032d3814e7c0fb359ec500d5e60b716b68e..ae677ce941400f5703b6f0150e516df40ddb6bc3 100644 GIT binary patch delta 3924 zcmai1Yiu0V6~6bLncW>bZnB9J2ZzLilPC?2H}l+GJ59>q#LhZiJMkmVx&pKIj=kgE zopJUNKPXzvpX0NV#I)vX~g zfT}27>9ffX8n%D^TJ4Rb8lVv;#^UCvH5gB140AATjaF`03A?b3&(&=AQm$u_|Ei|@ ze@!(sELh6w#|(Xf*k{85V$jQ?T^biL^I0oV7|zo@;qw-M zFgcYohI3`Kg3VGe5EjEhRg^s}k~Q38Wci-FKAzM~et&!-MNfN~jvxgTDJTXd5@lIr zXk52`v|wcQjBe(OIewoxYM8p7rK&vT&G%R%`H6T|r?~NKzA#=+LUH#-2rG)ZgJIED z4Y$Wlz9*hO7Ef5&GV4mS6bgi;a9EK^2w1dR^Yxj=F+H0z@>9GuQsi6WX=B97nnrw? zsvrjxSq({wKv=X>^L0(qg$aHEpiIL#xPTB;R7GjVENanw-NsldSGa0WH}ZU2)-tK5 zx>?e#ovy-FL>3KANLc5(Y5mJN;FLp;n$p@ELpz@56uKO={z>@Mm}l zeh<%6D?f*N1~^>lhzdt=j_^6c>j;k{?8|NIYb(*)2%dm3s3U(Q-y!?(75qzVVHLe? z`I|U%9hBo=E74`ey#l zyY9M;gex4FwbzD`0!?aA5<^l?+(<0dEZzqDxa%uiu*$~RGxWl?Rh3fY`Ke?)5e26^{04ve~#P|>YvrBsw< zwMkMAW~~uDm$S0-P)a$JCjt&sXerbjlAD>quqew5$v6)smqQhO5pq4OxttA(;U?)C zSj&RY7s1zuax*v_Y!bvJQ0q$py)2x3r@w_)t;A2!OFD*747%uF8%>zVZ0!3Zn4x9; zUYdpX;MuMRpJ03hE+BXvF3_R#@TJv+L2GYvVtpZ_YN^iFn-)jk!klwU5O^QKC-6Q+ z_$O@gGMLr~LRf~TCF5Mjgj687nN;8}qwmr+pWxYw$3CIu0gOW zJp})S_bA>!pw2_7J6pz5PP7(QK|Ny72}Cs9icUa~;udC4y!H^;P`%Jml-_3A+PyUy z4bNokLx1D#J3jsqHT*7uEATFbejRQsL3=$O2O6`bxH)tdVB{eLlK}B>%?H@dPbG6fME}p38 zyE^Tar}!0f6ZP9?_Vm~tkM>}{{m`Q+?r68SM$_=|jD5$MYMVb*X}|eEEf(!t9;>ly zPyNcitGM0X{R(G4a`tBX^E&ns<_fcdfpyOPd_Nq9b(EtAihEYGXyY#JYST;mL3xn2 zo7SL{g`yxxgQBde3n}T;GF5F>#efo0l(4+VU#>4L)0e|b_2qE05Ddr^HH^dd{hym2 zOrAmH8OrEMQvBL3%tnv1T6laqDd#h}cqo_*heTZ*jVtN6EG4s3!nBY|M|-w0n2adFl#4@d8ap`bjpd}KFWV(w-WBsZ*G^LIWNvbfMNgExRRx!~wT9{wBKU(PR zZ%PgHPqxJRJF^4*YARw(7)K;$U2-IGq%%F7Zn9!WI<3f(mcV{Q zEe03$-c2Dzm7EyH@G62=>3;qJ8aG3f`+s{`(z%4d_J8o=EYJ90(?-zd`<~@SezF2r z&-(dyz~-6tRhXKL&_|$8fLgr_Cl%I9K1J|N@+tlP4k^xXv`*t~Gpwd@nAxij(>|Kd z4JR!t9pUpy!%R6cH#fx7xACl=r|oXSUAluGD&+Zed^qJySoF6LKVn&lz|z3F+L_6r z@{lVoOob#`NH~NW2PqYf^g33@DYDMz3KZV`ULxkO$XgblFzBT}8aIt;TH>8(7VWAtvzB&iN=Oa6Wdgm7$OfE3FWY|RIha}9Z=Zj1xBbAmI-5Tegqg;} zcF(z18=tAOt#cdfi{~0EzCP6Ft!Ze$-?)<|`(}K=P4WlNykcKCYueV?8e1u@x|-~G G`~Lts9O>8q delta 722 zcmY*WQAm?f6u##_S2x_6`yEbjq$3xU^Vdop3aR}T+A3&KghDV^PFuK5H9*)3>Shk*K{0_s!&&KACe zwX_r&Da0;{ARHyiTFp-8+PUHJFW|Ik!(iTpZDQ>#f%9Y*J-9B`KF4^; z5$$UYv}jWbRBDY1xQfR5+H_@3C)`GDZ!J`@54j38{(0XAYwsusR9tsoU5 z&%{|z()*~eYXT@Q__T$bp4!xz_K4#XL{g!HB+w;Z#du=wfdt=0`7M1xGMmGsfMf}} zq!G9-9U@uLSmfE|yC4z5hO%#q;+-dSWkD6Name: {{ entity.name }} +

      Name: {{ entity.name }}

      Average rating: {{ entity.average_rating }} {% block entity_info %} {% endblock %} diff --git a/backend/postings/views.py b/backend/postings/views.py index 61c25b9..d8ae6df 100644 --- a/backend/postings/views.py +++ b/backend/postings/views.py @@ -24,6 +24,7 @@ def universities(request): def university_entity(request, university_id): try: university = University.objects.get(pk=university_id) + university.average_rating = university.getAverageRating() except University.DoesNotExist: raise Http404("University does not exist") return render(request, 'postings/entity_pages/university.html', {'entity': university}) -- 2.34.1 From fa67dc6c3478a2ffbbd16835498e392a564b088c Mon Sep 17 00:00:00 2001 From: andrewlalis Date: Wed, 3 Oct 2018 22:00:08 +0200 Subject: [PATCH 06/31] Added a form object and the ability to write reviews. Only needs styling now. --- backend/RateMyCourse/urls.py | 3 ++ backend/db.sqlite3 | Bin 77824 -> 77824 bytes backend/postings/forms.py | 12 ++++++ backend/postings/models.py | 2 + .../postings/entity_pages/entity.html | 28 +++++++++++++- backend/postings/views.py | 35 +++++++++++++++++- 6 files changed, 77 insertions(+), 3 deletions(-) create mode 100644 backend/postings/forms.py diff --git a/backend/RateMyCourse/urls.py b/backend/RateMyCourse/urls.py index cc3e5cb..00a147e 100644 --- a/backend/RateMyCourse/urls.py +++ b/backend/RateMyCourse/urls.py @@ -24,6 +24,9 @@ urlpatterns = [ # / routes to index.html path('', views.index, name='homepage'), + # /reviews routes to the endpoint for POSTing new reviews. + path('reviews', views.post_review, name='post_review'), + # /universities routes to a list of universities. path('universities', views.universities, name='universities_list'), diff --git a/backend/db.sqlite3 b/backend/db.sqlite3 index ae677ce941400f5703b6f0150e516df40ddb6bc3..823e9728193627bbd30a3deb9a2ae0eb65b50980 100644 GIT binary patch delta 735 zcmZvZzi-n(6vurz+fo_{rGljbsc$Pnt;sn*YG;c&Kr(^g55S49^(l_8@|_!HN-QC< zg8COA7FHBhu<;kb-_Uk|rAryg&<;G87D0-1`kwCnxc7PQ%?{1kq51kQ>AktPMS34z ztX7CUpH*JIuiEs;pcnKf{XviDH+nK(HowrSNz25xC?O@QP;3A6(d~EUClkYu4SGsX z=y!UIX=fPzmEJL_LF_`TLd-(w{Ot3ssA?Mr27OgJFOA3rd1@T&FPm?t`HH<{kk$NQ zr&Bhp$DGFy^K2-FuqTobLZKl`#2!zT&>SDpb;LT1f*=J99CNNA5h!D{$WdVn0}Ugd zh-3#d`i|qcHRf%w+D5Go%x^dA?Z&3#`n9R=HUIBoHP+1UTL`z6uXQ@au%1Uk0UjN3 z=yUZK*rb=?v(E=XrZ~h>E0Ei;9gJkAV3*6?n1j+;D0qlCDPPAw5D@>Gj-v^5Ar?ap z*j-R0FR(WJwu`JDbA9(;)IXlO>z1ThHptqug4BGHa;+zzB7xT>_8<Name: {{ entity.name }} Average rating: {{ entity.average_rating }} +

      Name: {{ entity.name }}

      Average rating: {{ entity.average_rating|floatformat:"-2" }} +{# Child templates can redefine this block for displaying data pertaining to that specific entity. #} {% block entity_info %} {% endblock %} +{# This section displays all reviews for a given entity. #}

      Reviews

        @@ -21,4 +23,28 @@
      +{# This section is where the user can write a review for a particular entity and submit it. #} +
      +

      Write a Review

      +
      + + +
      + + + +
      + + + +
      + + {# The following csrf_token and input fields are hidden values needed for form submission. #} + {% csrf_token %} + + + +
      +
      + {% endblock %} \ No newline at end of file diff --git a/backend/postings/views.py b/backend/postings/views.py index d8ae6df..4eb60cb 100644 --- a/backend/postings/views.py +++ b/backend/postings/views.py @@ -1,6 +1,7 @@ from django.shortcuts import render -from django.http import HttpResponse, Http404 +from django.http import HttpResponse, Http404, HttpResponseBadRequest, HttpResponseRedirect from postings.models import * +from postings.forms import * # Create your views here. @@ -41,4 +42,34 @@ def course_entity(request, course_id): course = Course.objects.get(pk=course_id) except Course.DoesNotExist: raise Http404("Course does not exist") - return render(request, 'postings/entity_pages/course.html', {'entity': course}) \ No newline at end of file + return render(request, 'postings/entity_pages/course.html', {'entity': course}) + +# The view for receiving POST requests for new reviews. +def post_review(request): + if request.method == 'POST': + form = EntityReviewForm(request.POST) + if form.is_valid(): + # Only if the request is a POST and the form is valid do we do anything. + rating = form.cleaned_data['rating'] + title = form.cleaned_data['title'] + content = form.cleaned_data['content'] + entity_id = form.cleaned_data['entity_id'] + entity = RateableEntity.objects.get(pk=entity_id) + + # Creates the new Review object from the posted data. + review = Review.objects.create( + rating=rating, + title=title, + content=content, + rateable_entity=entity + ) + + # Send the user back to the entity they were viewing. + redirect_path = '/' + if entity.entity_type == RateableEntity.UNIVERSITY: + redirect_path = '/universities/' + str(entity_id) + elif entity.entity_type == RateableEntity.COURSE: + redirect_path = '/courses/' + str(entity_id) + return HttpResponseRedirect(redirect_path) + + return HttpResponseBadRequest("Bad Request") \ No newline at end of file -- 2.34.1 From fbb0c890a1ae01cad635f269f6080db7939c46d8 Mon Sep 17 00:00:00 2001 From: andrewlalis Date: Wed, 3 Oct 2018 22:59:09 +0200 Subject: [PATCH 07/31] Removed old paths, now use just a rateables path for all things. --- backend/RateMyCourse/urls.py | 14 ++--- backend/db.sqlite3 | Bin 77824 -> 77824 bytes .../postings/static/postings}/favicon.ico | Bin .../postings/collections/courses.html | 11 ---- .../postings/collections/universities.html | 11 ---- .../postings/entity_pages/course.html | 11 ---- .../postings/templates/postings/index.html | 4 +- .../templates/postings/rateables/course.html | 11 ++++ .../entities.html} | 4 +- .../{entity_pages => rateables}/entity.html | 8 +-- .../templates/postings/rateables/review.html | 4 ++ .../university.html | 4 +- backend/postings/views.py | 53 ++++++++++-------- 13 files changed, 57 insertions(+), 78 deletions(-) rename {frontpage => backend/postings/static/postings}/favicon.ico (100%) delete mode 100644 backend/postings/templates/postings/collections/courses.html delete mode 100644 backend/postings/templates/postings/collections/universities.html delete mode 100644 backend/postings/templates/postings/entity_pages/course.html create mode 100644 backend/postings/templates/postings/rateables/course.html rename backend/postings/templates/postings/{collections/collection.html => rateables/entities.html} (75%) rename backend/postings/templates/postings/{entity_pages => rateables}/entity.html (79%) create mode 100644 backend/postings/templates/postings/rateables/review.html rename backend/postings/templates/postings/{entity_pages => rateables}/university.html (65%) diff --git a/backend/RateMyCourse/urls.py b/backend/RateMyCourse/urls.py index 00a147e..2f70aec 100644 --- a/backend/RateMyCourse/urls.py +++ b/backend/RateMyCourse/urls.py @@ -27,17 +27,11 @@ urlpatterns = [ # /reviews routes to the endpoint for POSTing new reviews. path('reviews', views.post_review, name='post_review'), - # /universities routes to a list of universities. - path('universities', views.universities, name='universities_list'), + # /rateables routes to a list of all rateable items: courses and universities. + path('rateables', views.rateables, name='rateables'), - # /universities/ routes to a specific university. - path('universities/', views.university_entity, name='university entity'), - - # /courses routes to a list of courses. - path('courses', views.courses, name='courses_list'), - - # /courses/ routes to a specific course. - path('courses/', views.course_entity, name='course entity'), + # /rateables/ routes to a specific rateable entity. + path('rateables/', views.rateable_entity, name='rateable_entity'), # static files (*.css, *.js, *.jpg etc.) served on / # (assuming Django uses /static/ and /media/ for static/media urls) diff --git a/backend/db.sqlite3 b/backend/db.sqlite3 index 823e9728193627bbd30a3deb9a2ae0eb65b50980..ef66ed954b5bca41d0b26e7fed3a786748c63b36 100644 GIT binary patch delta 330 zcmZuty-EW?7~JLC%Ys2Mwt{|OkqAlH#Gi}lqE(D3#23h2Tyl$XFL)QiRVLsA=u3#L z9B3n0S@{SdkfhK?5N#}C;cD%`3=G3eG5s;?kJ;t&e2oxtVEBitj7@8|jnyROaX)!+ zv&3OY;2XZ+6DIHiZ!nBg>7{!YZ&tNeiW@7rd(zwe| z#u60j1nQ={2j>I9=LlUN99AlnSVy7kcv7PZ&~;=LkA0mE@k~1Hc7!L|@1dik&{MjF zj_Y?r?08Y2nn4y_V^o+9P^+fI&_~y((`|Vnx)BEcsr0o(rP0BjCuO_oIqEE5+!cjV vt{`$^1B;?8O6AR+yeMsL+oJe?VhfvF<{k>O-;?%X7N_tXfK(ILS;~F@8%kWq delta 134 zcmZp8z|!!5Wr8%X7Xt%>4-kWBrimKnj9wcPVGd}_<`396a$GrK`ez}Crf-3KsCo8Z>@G=4o d^#o!AAl3sac*8tNgJn630wc?I79GYv%mAr%Cz1dF diff --git a/frontpage/favicon.ico b/backend/postings/static/postings/favicon.ico similarity index 100% rename from frontpage/favicon.ico rename to backend/postings/static/postings/favicon.ico diff --git a/backend/postings/templates/postings/collections/courses.html b/backend/postings/templates/postings/collections/courses.html deleted file mode 100644 index 0fc63cb..0000000 --- a/backend/postings/templates/postings/collections/courses.html +++ /dev/null @@ -1,11 +0,0 @@ -{% extends "postings/collections/collection.html" %} - -{# Represents a list of university entities. #} - -{% block collection_name %} -

      Courses

      -{% endblock %} - -{% block entity %} -

      {{ entity.name }}

      -{% endblock %} \ No newline at end of file diff --git a/backend/postings/templates/postings/collections/universities.html b/backend/postings/templates/postings/collections/universities.html deleted file mode 100644 index bb5374d..0000000 --- a/backend/postings/templates/postings/collections/universities.html +++ /dev/null @@ -1,11 +0,0 @@ -{% extends "postings/collections/collection.html" %} - -{# Represents a list of university entities. #} - -{% block collection_name %} -

      Universities

      -{% endblock %} - -{% block entity %} -

      {{ entity.name }}

      -{% endblock %} \ No newline at end of file diff --git a/backend/postings/templates/postings/entity_pages/course.html b/backend/postings/templates/postings/entity_pages/course.html deleted file mode 100644 index 8508196..0000000 --- a/backend/postings/templates/postings/entity_pages/course.html +++ /dev/null @@ -1,11 +0,0 @@ -{% extends "postings/entity_pages/entity.html" %} - -{% block entity_info %} - Taught at: {{ entity.taught_at_university.name }} -

      Professors

      -
        - {% for professor in entity.professors.all %} -
      • {{ professor.name }}
      • - {% endfor %} -
      -{% endblock %} \ No newline at end of file diff --git a/backend/postings/templates/postings/index.html b/backend/postings/templates/postings/index.html index 6b4fc7b..2c2743d 100644 --- a/backend/postings/templates/postings/index.html +++ b/backend/postings/templates/postings/index.html @@ -10,8 +10,8 @@ diff --git a/backend/postings/templates/postings/rateables/course.html b/backend/postings/templates/postings/rateables/course.html new file mode 100644 index 0000000..6601e3d --- /dev/null +++ b/backend/postings/templates/postings/rateables/course.html @@ -0,0 +1,11 @@ +{% extends "postings/rateables/entity.html" %} + +{% block entity_info %} + Taught at: {{ entity.taught_at_university.name }} +

      Professors

      +
        + {% for professor in entity.professors.all %} +
      • {{ professor.name }}
      • + {% endfor %} +
      +{% endblock %} \ No newline at end of file diff --git a/backend/postings/templates/postings/collections/collection.html b/backend/postings/templates/postings/rateables/entities.html similarity index 75% rename from backend/postings/templates/postings/collections/collection.html rename to backend/postings/templates/postings/rateables/entities.html index 90d7f3b..46d09b6 100644 --- a/backend/postings/templates/postings/collections/collection.html +++ b/backend/postings/templates/postings/rateables/entities.html @@ -10,9 +10,7 @@
        {% for entity in entities %}
      • - {% block entity %} - {{ entity.name }} - {% endblock %} + {{ entity.name }}
      • {% endfor %}
      diff --git a/backend/postings/templates/postings/entity_pages/entity.html b/backend/postings/templates/postings/rateables/entity.html similarity index 79% rename from backend/postings/templates/postings/entity_pages/entity.html rename to backend/postings/templates/postings/rateables/entity.html index 49aa6ff..4b322a5 100644 --- a/backend/postings/templates/postings/entity_pages/entity.html +++ b/backend/postings/templates/postings/rateables/entity.html @@ -4,9 +4,10 @@ {% block content %} -

      Name: {{ entity.name }}

      Average rating: {{ entity.average_rating|floatformat:"-2" }} +

      Name: {{ entity.name }} {{ entity.average }}

      +

      Average rating: {{ entity.average_rating|floatformat:"-2" }}

      -{# Child templates can redefine this block for displaying data pertaining to that specific entity. #} +{# Depending on the type of entity, some detailed info is provided here. #} {% block entity_info %} {% endblock %} @@ -16,8 +17,7 @@
        {% for review in entity.review_set.all %}
      • -

        {{ review.title }}

        {{ review.rating }} -

        {{ review.content }} + {% include "postings/rateables/review.html" with review=review only %}

      • {% endfor %}
      diff --git a/backend/postings/templates/postings/rateables/review.html b/backend/postings/templates/postings/rateables/review.html new file mode 100644 index 0000000..0dec975 --- /dev/null +++ b/backend/postings/templates/postings/rateables/review.html @@ -0,0 +1,4 @@ +{# Template for displaying one review. #} + +

      {{ review.title }}

      {{ review.rating }} +

      {{ review.content }}

      \ No newline at end of file diff --git a/backend/postings/templates/postings/entity_pages/university.html b/backend/postings/templates/postings/rateables/university.html similarity index 65% rename from backend/postings/templates/postings/entity_pages/university.html rename to backend/postings/templates/postings/rateables/university.html index 0ea0b8c..c477e6b 100644 --- a/backend/postings/templates/postings/entity_pages/university.html +++ b/backend/postings/templates/postings/rateables/university.html @@ -1,10 +1,10 @@ -{% extends "postings/entity_pages/entity.html" %} +{% extends "postings/rateables/entity.html" %} {% block entity_info %}

      Courses

      Professors

      diff --git a/backend/postings/views.py b/backend/postings/views.py index 4eb60cb..481b24a 100644 --- a/backend/postings/views.py +++ b/backend/postings/views.py @@ -11,38 +11,43 @@ def index(request): search_query = request.GET.get('search_query', None) results = None if search_query: + # Filter objects based on case-insensitive contains filter. results = RateableEntity.objects.filter(name__icontains=search_query) return render(request, 'postings/index.html', {'results': results}) -# The view for a listing of universities. -def universities(request): - universities_list = University.objects.all() - context = {'entities': universities_list} - return render(request, 'postings/collections/universities.html', context) +# The view for listing all rateable entities. +def rateables(request): + entity_type = request.GET.get('type', None) + entities = None + if entity_type == "university": + entities = University.objects.all() + elif entity_type == "course": + entities = Course.objects.all() + else: + entities = RateableEntity.objects.all() + return render(request, "postings/rateables/entities.html", {'entities': entities}) -# The view for /universities/ Displays one university entity. -def university_entity(request, university_id): +# The view for any rateable entity. +def rateable_entity(request, entity_id): try: - university = University.objects.get(pk=university_id) - university.average_rating = university.getAverageRating() - except University.DoesNotExist: - raise Http404("University does not exist") - return render(request, 'postings/entity_pages/university.html', {'entity': university}) + entity = RateableEntity.objects.get(pk=entity_id) -# The view for a listing of courses. -def courses(request): - courses_list = Course.objects.all() - context = {'entities': courses_list} - return render(request, 'postings/collections/courses.html', context) + # Try and get a more specific entity type from what is provided. + if entity.entity_type == RateableEntity.UNIVERSITY: + entity = University.objects.get(pk=entity.pk) + template = "university.html" + elif entity.entity_type == RateableEntity.COURSE: + entity = Course.objects.get(pk=entity.pk) + template = "course.html" -# The view for a specific course entity. -def course_entity(request, course_id): - try: - course = Course.objects.get(pk=course_id) - except Course.DoesNotExist: - raise Http404("Course does not exist") - return render(request, 'postings/entity_pages/course.html', {'entity': course}) + # Set any auxiliary variables needed, like average rating. + # This MUST be done after categorizing the object above. + entity.average_rating = entity.getAverageRating() + + except RateableEntity.DoesNotExist: + raise Http404("RateableEntity with id " + str(entity_id) + " does not exist.") + return render(request, "postings/rateables/" + template, {'entity': entity}) # The view for receiving POST requests for new reviews. def post_review(request): -- 2.34.1 From a8597b1ce425964e8e0ac9a3a36439e228220b56 Mon Sep 17 00:00:00 2001 From: andrewlalis Date: Wed, 3 Oct 2018 23:08:57 +0200 Subject: [PATCH 08/31] Added date display to review html. --- backend/db.sqlite3 | Bin 77824 -> 77824 bytes .../templates/postings/rateables/review.html | 5 ++++- backend/postings/views.py | 12 +++++------- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/backend/db.sqlite3 b/backend/db.sqlite3 index ef66ed954b5bca41d0b26e7fed3a786748c63b36..e6ee6dc39ee4fd2bed65d254cf5f6a73cc64540a 100644 GIT binary patch delta 594 zcmchSu}%U(5QcA^GvUC-#zu|P5fdQ?9EeyE3q!#(;K422hLtmS3rH*gV?(EJVQVgi zSosJP#KeSNLMP`- z8VnS8hc|eEJ9vN_7{C*Z{6+N=7UqEv&^~LxANAK&=^iTZEFF(<4`aB6p}c*S?kfnY zpb%|Z0{-|qYz2Yz6v)q2Nl)rWq}?rOL4|A|uV%AEfh>1f#TFY_tP6A+)ID%niCQ`2 zOiWWnoa25AIV}sUGOI>g({+UkWHs3cn|bJ!Y{%hWX-tGYY&x#6kqIo) zl3DjCwrfrkbJ%3lG_y+4V~1E~mAXqk86-!}N=^+M@;7Zo<9aL|iRlqNf$>;IPh<=| vn%dG0!RY^4yH{{ review.title }} {{ review.rating }} +

      {{ review.title }}

      +Rating: {{ review.rating }}
      +Posted on {{ review.created_date|date:"j M, Y" }}
      +

      {{ review.content }}

      \ No newline at end of file diff --git a/backend/postings/views.py b/backend/postings/views.py index 481b24a..1f65c22 100644 --- a/backend/postings/views.py +++ b/backend/postings/views.py @@ -59,7 +59,10 @@ def post_review(request): title = form.cleaned_data['title'] content = form.cleaned_data['content'] entity_id = form.cleaned_data['entity_id'] - entity = RateableEntity.objects.get(pk=entity_id) + try: + entity = RateableEntity.objects.get(pk=entity_id) + except RateableEntity.DoesNotExist: + raise HttpResponseBadRequest("Bad Request: Invalid entity id.") # Creates the new Review object from the posted data. review = Review.objects.create( @@ -70,11 +73,6 @@ def post_review(request): ) # Send the user back to the entity they were viewing. - redirect_path = '/' - if entity.entity_type == RateableEntity.UNIVERSITY: - redirect_path = '/universities/' + str(entity_id) - elif entity.entity_type == RateableEntity.COURSE: - redirect_path = '/courses/' + str(entity_id) - return HttpResponseRedirect(redirect_path) + return HttpResponseRedirect('/rateables/' + str(entity_id)) return HttpResponseBadRequest("Bad Request") \ No newline at end of file -- 2.34.1 From 6d005520066278b9c49c631914e848ab13797c5b Mon Sep 17 00:00:00 2001 From: andrewlalis Date: Sat, 6 Oct 2018 08:10:29 +0200 Subject: [PATCH 09/31] Added website icon. --- backend/db.sqlite3 | Bin 77824 -> 77824 bytes website_icon.png | Bin 0 -> 13507 bytes website_icon.svg | 121 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 121 insertions(+) create mode 100644 website_icon.png create mode 100644 website_icon.svg diff --git a/backend/db.sqlite3 b/backend/db.sqlite3 index e6ee6dc39ee4fd2bed65d254cf5f6a73cc64540a..b64c046c45f42ed64f0ba4a890c19be9de0c6ee5 100644 GIT binary patch delta 215 zcmZp8z|!!5Wr8%L-$WT_M!$^-^4yGEn;W=WR`78#pJHJC!~C836Z1pnQ=0|0>|kbP zVdex%pWklEBEiLcj)D0j^Bd;p%#WDwGT&gn%zO^0{M%;5J=>UpiZ1UrOyOZ+G-P1* zWy)skWHj6?$fC#?9md7Uz$j|!=*Y>yT%3_vl86Nu85mmV8XD*tm?#(;Ss5By8C&RC eS{PYc8e*3*HZU@3jOU!5r^dK@ySp0WPEG)QpFW}h delta 123 zcmZp8z|!!5Wr8%L??f4AM&FGI^4yG^n;W=WR)}#jpJ!nH!~C836Z1pnXUtcb&ojSa zzP(wHWh?XM^V>~XfC?@%FnwD=q*4 diff --git a/website_icon.png b/website_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..8ed463a1ce6d8d6572d3081a8b4a3ccf13207c7a GIT binary patch literal 13507 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 dSky6Q-+m + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + -- 2.34.1 From 36f3d9fcde3385733eaa9c273dcbf89522e67769 Mon Sep 17 00:00:00 2001 From: ludger Date: Sat, 6 Oct 2018 21:18:18 +0200 Subject: [PATCH 10/31] Took some hours but I merged the frontend and the backend --- .../templates/postings/frontend/entity.html | 197 + .../templates/postings/frontend/landing.html | 74 + .../templates/postings/frontend/results.html | 117 + .../templates/postings/frontend/review.html | 20 + .../templates/postings/generic_page.html | 3 +- backend/postings/views.py | 8 +- frontpage/css/{main.css => style.css} | 21 +- frontpage/css/{main.css.map => style.css.map} | 6 +- frontpage/css/{main.scss => style.scss} | 25 +- frontpage/entity.html | 251 + frontpage/js/main.js | 67 +- frontpage/rateables/css/bootstrap-theme.css | 470 ++ .../rateables/css/bootstrap-theme.css.map | 1 + .../rateables/css/bootstrap-theme.min.css | 5 + frontpage/rateables/css/bootstrap.css | 6332 +++++++++++++++++ frontpage/rateables/css/bootstrap.css.map | 1 + frontpage/rateables/css/bootstrap.min.css | 5 + frontpage/rateables/css/style.css | 103 + frontpage/rateables/css/style.css.map | 7 + frontpage/rateables/css/style.scss | 122 + .../fonts/glyphicons-halflings-regular.eot | Bin 0 -> 20335 bytes .../fonts/glyphicons-halflings-regular.svg | 229 + .../fonts/glyphicons-halflings-regular.ttf | Bin 0 -> 41280 bytes .../fonts/glyphicons-halflings-regular.woff | Bin 0 -> 23320 bytes frontpage/rateables/js/load_reviews.js | 33 + frontpage/rateables/js/main.js | 102 + frontpage/rateables/js/post_review.js | 47 + .../js/templates/review_item.handlebars | 34 + frontpage/rateables/js/vendor/bootstrap.js | 2320 ++++++ .../rateables/js/vendor/bootstrap.min.js | 7 + .../rateables/js/vendor/handlebars-v4.0.12.js | 4838 +++++++++++++ .../rateables/js/vendor/jquery-1.11.2.min.js | 4 + .../modernizr-2.8.3-respond-1.4.2.min.js | 11 + frontpage/rateables/js/vendor/npm.js | 13 + frontpage/templResults.html | 116 + frontpage/templSearchbar.html | 82 + 36 files changed, 15658 insertions(+), 13 deletions(-) create mode 100644 backend/postings/templates/postings/frontend/entity.html create mode 100644 backend/postings/templates/postings/frontend/landing.html create mode 100644 backend/postings/templates/postings/frontend/results.html create mode 100644 backend/postings/templates/postings/frontend/review.html rename frontpage/css/{main.css => style.css} (82%) rename frontpage/css/{main.css.map => style.css.map} (80%) rename frontpage/css/{main.scss => style.scss} (84%) create mode 100644 frontpage/entity.html create mode 100644 frontpage/rateables/css/bootstrap-theme.css create mode 100644 frontpage/rateables/css/bootstrap-theme.css.map create mode 100644 frontpage/rateables/css/bootstrap-theme.min.css create mode 100644 frontpage/rateables/css/bootstrap.css create mode 100644 frontpage/rateables/css/bootstrap.css.map create mode 100644 frontpage/rateables/css/bootstrap.min.css create mode 100644 frontpage/rateables/css/style.css create mode 100644 frontpage/rateables/css/style.css.map create mode 100644 frontpage/rateables/css/style.scss create mode 100644 frontpage/rateables/fonts/glyphicons-halflings-regular.eot create mode 100644 frontpage/rateables/fonts/glyphicons-halflings-regular.svg create mode 100644 frontpage/rateables/fonts/glyphicons-halflings-regular.ttf create mode 100644 frontpage/rateables/fonts/glyphicons-halflings-regular.woff create mode 100644 frontpage/rateables/js/load_reviews.js create mode 100644 frontpage/rateables/js/main.js create mode 100644 frontpage/rateables/js/post_review.js create mode 100644 frontpage/rateables/js/templates/review_item.handlebars create mode 100644 frontpage/rateables/js/vendor/bootstrap.js create mode 100644 frontpage/rateables/js/vendor/bootstrap.min.js create mode 100644 frontpage/rateables/js/vendor/handlebars-v4.0.12.js create mode 100644 frontpage/rateables/js/vendor/jquery-1.11.2.min.js create mode 100644 frontpage/rateables/js/vendor/modernizr-2.8.3-respond-1.4.2.min.js create mode 100644 frontpage/rateables/js/vendor/npm.js create mode 100644 frontpage/templResults.html create mode 100644 frontpage/templSearchbar.html diff --git a/backend/postings/templates/postings/frontend/entity.html b/backend/postings/templates/postings/frontend/entity.html new file mode 100644 index 0000000..77261c3 --- /dev/null +++ b/backend/postings/templates/postings/frontend/entity.html @@ -0,0 +1,197 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      +
      +

      {{ entity.name }} {{ entity.average }}

      +

      {{ entity.average_rating|floatformat:"-2" }}

      +
      +
      +
      +
      +
      +
      +

      Average user rating

      +

      {{ entity.average_rating|floatformat:"-2" }} / 5

      +
      +
      +
      +

      Rating breakdown

      +
      +
      +
      5
      +
      +
      +
      +
      + 80% Complete (danger) +
      +
      +
      +
      0
      +
      +
      +
      +
      4
      +
      +
      +
      +
      + 80% Complete (danger) +
      +
      +
      +
      1
      +
      +
      +
      +
      3
      +
      +
      +
      +
      + 80% Complete (danger) +
      +
      +
      +
      1
      +
      +
      +
      +
      2
      +
      +
      +
      +
      + 80% Complete (danger) +
      +
      +
      +
      1
      +
      +
      +
      +
      1
      +
      +
      +
      +
      + 80% Complete (danger) +
      +
      +
      +
      0
      +
      +
      +
      + +
      +
      +
      +
      + + +
      +
      +
      + + + +
      + +
      +
      + {% for review in entity.review_set.all %} + {% include "postings/frontend/review.html" with review=review only %} + {% endfor %} +
      + +
      +
      + +
      + + + + + + + + + + + + \ No newline at end of file diff --git a/backend/postings/templates/postings/frontend/landing.html b/backend/postings/templates/postings/frontend/landing.html new file mode 100644 index 0000000..41ad856 --- /dev/null +++ b/backend/postings/templates/postings/frontend/landing.html @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      +

      Find rated courses

      +

      The best course reviews by your fellow students!

      +
      +
      +
      + +
      + +
      +
      +
      +
      +
      +
      + + + + + + + + + + + + + diff --git a/backend/postings/templates/postings/frontend/results.html b/backend/postings/templates/postings/frontend/results.html new file mode 100644 index 0000000..38d4744 --- /dev/null +++ b/backend/postings/templates/postings/frontend/results.html @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      +
      +
      +
      +

      + 160 Courses found for: "Software engineering" +

      + Request time (0.23 seconds) + +
      +
      +
      + +
      + +
      +
      +
      +
      + + {# Second section for displaying results, or whatever should be shown first. #} + {% if results %} + {% for entity in results %} +
      + + {% endfor %} + {% endif %} + +
      + + + + + + + + + +
      +
      +
      +
      +
      + + + + + + + + + + diff --git a/backend/postings/templates/postings/frontend/review.html b/backend/postings/templates/postings/frontend/review.html new file mode 100644 index 0000000..953e1fb --- /dev/null +++ b/backend/postings/templates/postings/frontend/review.html @@ -0,0 +1,20 @@ + + + +
      +
      +
      + + +
      {{ review.created_date|date:"j M, Y" }}
      +
      +
      +
      +
      + + +
      +
      {{ review.title }}
      +
      {{ review.content }}
      +
      +
      \ No newline at end of file diff --git a/backend/postings/templates/postings/generic_page.html b/backend/postings/templates/postings/generic_page.html index f49084f..d1a5f4f 100644 --- a/backend/postings/templates/postings/generic_page.html +++ b/backend/postings/templates/postings/generic_page.html @@ -5,7 +5,7 @@ - {% block title %}RateMyCourse{% endblock %} + {% block title %}RateMyCourse{% endblock %} @@ -13,7 +13,6 @@

      RateMyCourse

      - {# All of a page's content to display should be placed in here. #}
      {% block content %} diff --git a/backend/postings/views.py b/backend/postings/views.py index 1f65c22..4f0c918 100644 --- a/backend/postings/views.py +++ b/backend/postings/views.py @@ -3,6 +3,7 @@ from django.http import HttpResponse, Http404, HttpResponseBadRequest, HttpRespo from postings.models import * from postings.forms import * + # Create your views here. # The view for the homepage, or index.html @@ -13,8 +14,8 @@ def index(request): if search_query: # Filter objects based on case-insensitive contains filter. results = RateableEntity.objects.filter(name__icontains=search_query) - - return render(request, 'postings/index.html', {'results': results}) + return render(request, 'postings/frontend/results.html', {'results': results}) + return render(request, 'postings/frontend/landing.html', {'results': results}) # The view for listing all rateable entities. def rateables(request): @@ -47,7 +48,8 @@ def rateable_entity(request, entity_id): except RateableEntity.DoesNotExist: raise Http404("RateableEntity with id " + str(entity_id) + " does not exist.") - return render(request, "postings/rateables/" + template, {'entity': entity}) + return render(request, 'postings/frontend/entity.html', {'entity': entity}) + # return render(request, "postings/rateables/" + template, {'entity': entity}) # The view for receiving POST requests for new reviews. def post_review(request): diff --git a/frontpage/css/main.css b/frontpage/css/style.css similarity index 82% rename from frontpage/css/main.css rename to frontpage/css/style.css index 515b546..ab43fb5 100644 --- a/frontpage/css/main.css +++ b/frontpage/css/style.css @@ -1,5 +1,5 @@ .box { - position: relative; + position: absolute; width: 100%; background: #5850c7 url(https://d20ohkaloyme4g.cloudfront.net/img/hero-illustration-module.png) repeat; color: #fff; @@ -83,4 +83,21 @@ body { font-size: 24px; color: #d17581; } -/*# sourceMappingURL=main.css.map */ +.hr-line-dashed { + border-top: 1px dashed #E7EAEC; + color: #ffffff; + background-color: #ffffff; + height: 1px; + margin: 20px 0; } + +h2 { + font-size: 24px; + font-weight: 100; } + +.block3 { + background: white; } + +.search-form { + min-width: 60vw; } + +/*# sourceMappingURL=style.css.map */ diff --git a/frontpage/css/main.css.map b/frontpage/css/style.css.map similarity index 80% rename from frontpage/css/main.css.map rename to frontpage/css/style.css.map index 021c2fa..5b3cbef 100644 --- a/frontpage/css/main.css.map +++ b/frontpage/css/style.css.map @@ -1,7 +1,7 @@ { "version": 3, -"mappings": "AACA,IAAI;EACF,QAAQ,EAAE,QAAQ;EAClB,KAAK,EAAE,IAAI;EACX,UAAU,EAAE,0FAA0F;EACtG,KAAK,EAAE,IAAI;EACX,UAAU,EAAE,MAAM;EAClB,aAAa,EAAE,CAAC;EAChB,UAAU,EAAC,MAAM;;AAEnB,cAAe;EACb,OAAO,EAAE,IAAI;EACb,WAAW,EAAE,MAAM;EACnB,MAAM,EAAE,0BAA0B;EAClC,MAAM,EAAE,uBAAuB;EAC/B,MAAM,EAAE,kBAAkB;;AAE5B,iBAAiB;EACf,SAAS,EAAE,IAAI;;AAEjB,iBAAiB;EACf,aAAa,EAAE,IAAI;;AAOrB,KAAM;EACJ,UAAU,EAAE,OAAO;EACnB,QAAQ,EAAE,QAAQ;EAClB,KAAK,EAAE,IAAI;;AAGb,MAAM;EACJ,UAAU,EAAE,KAAK;;AAGnB,IAAK;EACH,WAAW,EAAE,IAAI;;AAEnB,SAAS;EACP,gBAAgB,EAAC,OAAO;EACxB,KAAK,EAAC,IAAI;;AAEZ,aAAa;EACX,gBAAgB,EAAC,OAAO;EACxB,MAAM,EAAC,iBAAiB;EACxB,OAAO,EAAC,mBAAmB;EAC3B,aAAa,EAAC,GAAG;;AAEnB,KAAK;EACH,WAAW,EAAC,GAAG;;AAEjB,iBAAiB;EACf,cAAc,EAAC,GAAG;;AAGpB,aAAa;EACX,gBAAgB,EAAC,OAAO;EACxB,MAAM,EAAC,iBAAiB;EACxB,OAAO,EAAC,IAAI;EACZ,aAAa,EAAC,GAAG;EACjB,aAAa,EAAC,IAAI;;AAEpB,kBAAkB;EAChB,SAAS,EAAC,IAAI;EACd,MAAM,EAAC,MAAM;;AAEf,kBAAkB;EAChB,SAAS,EAAC,IAAI;;AAEhB,kBAAkB;EAChB,SAAS,EAAC,IAAI;EACd,aAAa,EAAC,IAAI;;AAEpB,mBAAmB;EACjB,SAAS,EAAC,IAAI;EACd,WAAW,EAAC,GAAG;EACf,aAAa,EAAC,IAAI;;AAEpB,yBAAyB;EACvB,SAAS,EAAC,IAAI;;AAGhB,SAAU;EACR,kBAAkB,EAAE,WAAW;EAC/B,eAAe,EAAE,WAAW;EAC5B,UAAU,EAAE,WAAW;;AAGzB,MACA;EACE,MAAM,EAAE,MAAM;EACd,SAAS,EAAE,IAAI;EACf,KAAK,EAAE,OAAO", -"sources": ["main.scss"], +"mappings": "AACA,IAAI;EACF,QAAQ,EAAE,QAAQ;EAClB,KAAK,EAAE,IAAI;EACX,UAAU,EAAE,0FAA0F;EACtG,KAAK,EAAE,IAAI;EACX,UAAU,EAAE,MAAM;EAClB,aAAa,EAAE,CAAC;EAChB,UAAU,EAAC,MAAM;;AAEnB,cAAe;EACb,OAAO,EAAE,IAAI;EACb,WAAW,EAAE,MAAM;EACnB,MAAM,EAAE,0BAA0B;EAClC,MAAM,EAAE,uBAAuB;EAC/B,MAAM,EAAE,kBAAkB;;AAE5B,iBAAiB;EACf,SAAS,EAAE,IAAI;;AAEjB,iBAAiB;EACf,aAAa,EAAE,IAAI;;AAOrB,KAAM;EACJ,UAAU,EAAE,OAAO;EACnB,QAAQ,EAAE,QAAQ;EAClB,KAAK,EAAE,IAAI;;AAGb,MAAM;EACJ,UAAU,EAAE,KAAK;;AAGnB,IAAK;EACH,WAAW,EAAE,IAAI;;AAEnB,SAAS;EACP,gBAAgB,EAAC,OAAO;EACxB,KAAK,EAAC,IAAI;;AAEZ,aAAa;EACX,gBAAgB,EAAC,OAAO;EACxB,MAAM,EAAC,iBAAiB;EACxB,OAAO,EAAC,mBAAmB;EAC3B,aAAa,EAAC,GAAG;;AAEnB,KAAK;EACH,WAAW,EAAC,GAAG;;AAEjB,iBAAiB;EACf,cAAc,EAAC,GAAG;;AAGpB,aAAa;EACX,gBAAgB,EAAC,OAAO;EACxB,MAAM,EAAC,iBAAiB;EACxB,OAAO,EAAC,IAAI;EACZ,aAAa,EAAC,GAAG;EACjB,aAAa,EAAC,IAAI;;AAEpB,kBAAkB;EAChB,SAAS,EAAC,IAAI;EACd,MAAM,EAAC,MAAM;;AAEf,kBAAkB;EAChB,SAAS,EAAC,IAAI;;AAEhB,kBAAkB;EAChB,SAAS,EAAC,IAAI;EACd,aAAa,EAAC,IAAI;;AAEpB,mBAAmB;EACjB,SAAS,EAAC,IAAI;EACd,WAAW,EAAC,GAAG;EACf,aAAa,EAAC,IAAI;;AAEpB,yBAAyB;EACvB,SAAS,EAAC,IAAI;;AAGhB,SAAU;EACR,kBAAkB,EAAE,WAAW;EAC/B,eAAe,EAAE,WAAW;EAC5B,UAAU,EAAE,WAAW;;AAGzB,MACA;EACE,MAAM,EAAE,MAAM;EACd,SAAS,EAAE,IAAI;EACf,KAAK,EAAE,OAAO;;AAOhB,eAAgB;EACd,UAAU,EAAE,kBAAkB;EAC9B,KAAK,EAAE,OAAO;EACd,gBAAgB,EAAE,OAAO;EACzB,MAAM,EAAE,GAAG;EACX,MAAM,EAAE,MAAM;;AAGhB,EAAG;EACD,SAAS,EAAE,IAAI;EACf,WAAW,EAAE,GAAG;;AAElB,OAAQ;EACN,UAAU,EAAE,KAAK;;AAGnB,YAAY;EACV,SAAS,EAAC,IAAI", +"sources": ["style.scss"], "names": [], -"file": "main.css" +"file": "style.css" } \ No newline at end of file diff --git a/frontpage/css/main.scss b/frontpage/css/style.scss similarity index 84% rename from frontpage/css/main.scss rename to frontpage/css/style.scss index 2f1ca7d..6b91183 100644 --- a/frontpage/css/main.scss +++ b/frontpage/css/style.scss @@ -1,6 +1,6 @@ //Homepage .box{ - position: relative; + position: absolute; width: 100%; background: #5850c7 url(https://d20ohkaloyme4g.cloudfront.net/img/hero-illustration-module.png) repeat; color: #fff; @@ -98,4 +98,25 @@ body { .nopointer{ -} \ No newline at end of file +} + +.hr-line-dashed { + border-top: 1px dashed #E7EAEC; + color: #ffffff; + background-color: #ffffff; + height: 1px; + margin: 20px 0; +} + +h2 { + font-size: 24px; + font-weight: 100; +} +.block3 { + background: white; +} + +.search-form{ + min-width:60vw; +} + diff --git a/frontpage/entity.html b/frontpage/entity.html new file mode 100644 index 0000000..9689498 --- /dev/null +++ b/frontpage/entity.html @@ -0,0 +1,251 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      +
      +

      Software engineering and startups

      +

      Rijksuniversiteit Groningen

      +
      +
      +
      +
      +
      +
      +

      Average user rating

      +

      3 / 5

      + + + + + +
      +
      +
      +

      Rating breakdown

      +
      +
      +
      5
      +
      +
      +
      +
      + 80% Complete (danger) +
      +
      +
      +
      0
      +
      +
      +
      +
      4
      +
      +
      +
      +
      + 80% Complete (danger) +
      +
      +
      +
      1
      +
      +
      +
      +
      3
      +
      +
      +
      +
      + 80% Complete (danger) +
      +
      +
      +
      1
      +
      +
      +
      +
      2
      +
      +
      +
      +
      + 80% Complete (danger) +
      +
      +
      +
      1
      +
      +
      +
      +
      1
      +
      +
      +
      +
      + 80% Complete (danger) +
      +
      +
      +
      0
      +
      +
      +
      + +
      +
      +
      +
      + + +
      +
      +
      + + + +
      + +
      +
      + +
      + +
      +
      + + +
      January 29, 2016
      1 day ago
      +
      +
      +
      +
      + + + + + +
      +
      Course review 3
      +
      Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley
      +
      +
      + + + + + +
      +
      +
      + +
      + + + + + + + + + + + + \ No newline at end of file diff --git a/frontpage/js/main.js b/frontpage/js/main.js index b61dd7d..75bf7e7 100644 --- a/frontpage/js/main.js +++ b/frontpage/js/main.js @@ -1,3 +1,8 @@ +// This is frontend javascript, DONT CHANGE!! + + + + (function(e){var t,o={className:"autosizejs",append:"",callback:!1,resizeDelay:10},i='",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,c.appendChild(b),b.innerHTML="",k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,k.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){k.noCloneEvent=!1}),b.cloneNode(!0).click()),null==k.deleteExpando){k.deleteExpando=!0;try{delete b.test}catch(d){k.deleteExpando=!1}}}(),function(){var b,c,d=y.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(k[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),k[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var X=/^(?:input|select|textarea)$/i,Y=/^key/,Z=/^(?:mouse|pointer|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=/^([^.]*)(?:\.(.+)|)$/;function ab(){return!0}function bb(){return!1}function cb(){try{return y.activeElement}catch(a){}}m.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=m.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof m===K||a&&m.event.triggered===a.type?void 0:m.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(E)||[""],h=b.length;while(h--)f=_.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=m.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=m.event.special[o]||{},l=m.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&m.expr.match.needsContext.test(e),namespace:p.join(".")},i),(n=g[o])||(n=g[o]=[],n.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?n.splice(n.delegateCount++,0,l):n.push(l),m.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m.hasData(a)&&m._data(a);if(r&&(k=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=_.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=m.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,n=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=n.length;while(f--)g=n[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(n.splice(f,1),g.selector&&n.delegateCount--,l.remove&&l.remove.call(a,g));i&&!n.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||m.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)m.event.remove(a,o+b[j],c,d,!0);m.isEmptyObject(k)&&(delete r.handle,m._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,n,o=[d||y],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||y,3!==d.nodeType&&8!==d.nodeType&&!$.test(p+m.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[m.expando]?b:new m.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:m.makeArray(c,[b]),k=m.event.special[p]||{},e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!m.isWindow(d)){for(i=k.delegateType||p,$.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||y)&&o.push(l.defaultView||l.parentWindow||a)}n=0;while((h=o[n++])&&!b.isPropagationStopped())b.type=n>1?i:k.bindType||p,f=(m._data(h,"events")||{})[b.type]&&m._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&m.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&m.acceptData(d)&&g&&d[p]&&!m.isWindow(d)){l=d[g],l&&(d[g]=null),m.event.triggered=p;try{d[p]()}catch(r){}m.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=m.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(m._data(this,"events")||{})[a.type]||[],k=m.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=m.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((m.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?m(c,this).index(i)>=0:m.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h]","i"),hb=/^\s+/,ib=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,jb=/<([\w:]+)/,kb=/\s*$/g,rb={option:[1,""],legend:[1,"
      ","
      "],area:[1,"",""],param:[1,"",""],thead:[1,"","
      "],tr:[2,"","
      "],col:[2,"","
      "],td:[3,"","
      "],_default:k.htmlSerialize?[0,"",""]:[1,"X
      ","
      "]},sb=db(y),tb=sb.appendChild(y.createElement("div"));rb.optgroup=rb.option,rb.tbody=rb.tfoot=rb.colgroup=rb.caption=rb.thead,rb.th=rb.td;function ub(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==K?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==K?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||m.nodeName(d,b)?f.push(d):m.merge(f,ub(d,b));return void 0===b||b&&m.nodeName(a,b)?m.merge([a],f):f}function vb(a){W.test(a.type)&&(a.defaultChecked=a.checked)}function wb(a,b){return m.nodeName(a,"table")&&m.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function xb(a){return a.type=(null!==m.find.attr(a,"type"))+"/"+a.type,a}function yb(a){var b=pb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function zb(a,b){for(var c,d=0;null!=(c=a[d]);d++)m._data(c,"globalEval",!b||m._data(b[d],"globalEval"))}function Ab(a,b){if(1===b.nodeType&&m.hasData(a)){var c,d,e,f=m._data(a),g=m._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)m.event.add(b,c,h[c][d])}g.data&&(g.data=m.extend({},g.data))}}function Bb(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!k.noCloneEvent&&b[m.expando]){e=m._data(b);for(d in e.events)m.removeEvent(b,d,e.handle);b.removeAttribute(m.expando)}"script"===c&&b.text!==a.text?(xb(b).text=a.text,yb(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),k.html5Clone&&a.innerHTML&&!m.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&W.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}m.extend({clone:function(a,b,c){var d,e,f,g,h,i=m.contains(a.ownerDocument,a);if(k.html5Clone||m.isXMLDoc(a)||!gb.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(tb.innerHTML=a.outerHTML,tb.removeChild(f=tb.firstChild)),!(k.noCloneEvent&&k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||m.isXMLDoc(a)))for(d=ub(f),h=ub(a),g=0;null!=(e=h[g]);++g)d[g]&&Bb(e,d[g]);if(b)if(c)for(h=h||ub(a),d=d||ub(f),g=0;null!=(e=h[g]);g++)Ab(e,d[g]);else Ab(a,f);return d=ub(f,"script"),d.length>0&&zb(d,!i&&ub(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,l,n=a.length,o=db(b),p=[],q=0;n>q;q++)if(f=a[q],f||0===f)if("object"===m.type(f))m.merge(p,f.nodeType?[f]:f);else if(lb.test(f)){h=h||o.appendChild(b.createElement("div")),i=(jb.exec(f)||["",""])[1].toLowerCase(),l=rb[i]||rb._default,h.innerHTML=l[1]+f.replace(ib,"<$1>")+l[2],e=l[0];while(e--)h=h.lastChild;if(!k.leadingWhitespace&&hb.test(f)&&p.push(b.createTextNode(hb.exec(f)[0])),!k.tbody){f="table"!==i||kb.test(f)?""!==l[1]||kb.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;while(e--)m.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j)}m.merge(p,h.childNodes),h.textContent="";while(h.firstChild)h.removeChild(h.firstChild);h=o.lastChild}else p.push(b.createTextNode(f));h&&o.removeChild(h),k.appendChecked||m.grep(ub(p,"input"),vb),q=0;while(f=p[q++])if((!d||-1===m.inArray(f,d))&&(g=m.contains(f.ownerDocument,f),h=ub(o.appendChild(f),"script"),g&&zb(h),c)){e=0;while(f=h[e++])ob.test(f.type||"")&&c.push(f)}return h=null,o},cleanData:function(a,b){for(var d,e,f,g,h=0,i=m.expando,j=m.cache,l=k.deleteExpando,n=m.event.special;null!=(d=a[h]);h++)if((b||m.acceptData(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)n[e]?m.event.remove(d,e):m.removeEvent(d,e,g.handle);j[f]&&(delete j[f],l?delete d[i]:typeof d.removeAttribute!==K?d.removeAttribute(i):d[i]=null,c.push(f))}}}),m.fn.extend({text:function(a){return V(this,function(a){return void 0===a?m.text(this):this.empty().append((this[0]&&this[0].ownerDocument||y).createTextNode(a))},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?m.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||m.cleanData(ub(c)),c.parentNode&&(b&&m.contains(c.ownerDocument,c)&&zb(ub(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&m.cleanData(ub(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&m.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return m.clone(this,a,b)})},html:function(a){return V(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(fb,""):void 0;if(!("string"!=typeof a||mb.test(a)||!k.htmlSerialize&&gb.test(a)||!k.leadingWhitespace&&hb.test(a)||rb[(jb.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(ib,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(m.cleanData(ub(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,m.cleanData(ub(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,n=this,o=l-1,p=a[0],q=m.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&nb.test(p))return this.each(function(c){var d=n.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(i=m.buildFragment(a,this[0].ownerDocument,!1,this),c=i.firstChild,1===i.childNodes.length&&(i=c),c)){for(g=m.map(ub(i,"script"),xb),f=g.length;l>j;j++)d=i,j!==o&&(d=m.clone(d,!0,!0),f&&m.merge(g,ub(d,"script"))),b.call(this[j],d,j);if(f)for(h=g[g.length-1].ownerDocument,m.map(g,yb),j=0;f>j;j++)d=g[j],ob.test(d.type||"")&&!m._data(d,"globalEval")&&m.contains(h,d)&&(d.src?m._evalUrl&&m._evalUrl(d.src):m.globalEval((d.text||d.textContent||d.innerHTML||"").replace(qb,"")));i=c=null}return this}}),m.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){m.fn[a]=function(a){for(var c,d=0,e=[],g=m(a),h=g.length-1;h>=d;d++)c=d===h?this:this.clone(!0),m(g[d])[b](c),f.apply(e,c.get());return this.pushStack(e)}});var Cb,Db={};function Eb(b,c){var d,e=m(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:m.css(e[0],"display");return e.detach(),f}function Fb(a){var b=y,c=Db[a];return c||(c=Eb(a,b),"none"!==c&&c||(Cb=(Cb||m("