diff --git a/feature_use_tracker/__init__.py b/feature_use_tracker/__init__.py new file mode 100644 index 0000000000..c8885fe7a6 --- /dev/null +++ b/feature_use_tracker/__init__.py @@ -0,0 +1,11 @@ +# Copyright (C) 2017 Semester.ly Technologies, LLC +# +# Semester.ly is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Semester.ly is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. \ No newline at end of file diff --git a/feature_use_tracker/admin.py b/feature_use_tracker/admin.py new file mode 100644 index 0000000000..c698ff635c --- /dev/null +++ b/feature_use_tracker/admin.py @@ -0,0 +1,15 @@ +# Copyright (C) 2017 Semester.ly Technologies, LLC +# +# Semester.ly is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Semester.ly is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +from django.contrib import admin + +# Register your models here. diff --git a/feature_use_tracker/apps.py b/feature_use_tracker/apps.py new file mode 100644 index 0000000000..ad1c31e41c --- /dev/null +++ b/feature_use_tracker/apps.py @@ -0,0 +1,18 @@ +# Copyright (C) 2017 Semester.ly Technologies, LLC +# +# Semester.ly is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Semester.ly is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +from django.apps import AppConfig + + +class FeatureUseTrackerConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'feature_use_tracker' diff --git a/feature_use_tracker/migrations/__init__.py b/feature_use_tracker/migrations/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/feature_use_tracker/models.py b/feature_use_tracker/models.py new file mode 100644 index 0000000000..c0643a608f --- /dev/null +++ b/feature_use_tracker/models.py @@ -0,0 +1,35 @@ +# Copyright (C) 2017 Semester.ly Technologies, LLC +# +# Semester.ly is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Semester.ly is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +from django.db import models +from django.contrib.auth.models import User +from django.utils.translation import gettext_lazy as _ + +class Feature(models.TextChoices): + COMPARE_TIMETABLES = "CT", _("Compare Timetables") + SIS_ADD_TO_CART = "SATC", _("SIS Add To Cart") + SCREENSHOT = "SS", _("Screenshot") + CUSTOM_EVENT = "CE", _("Custom Event") + DRAG_SEARCH = "DS", _("Custom Event") + EXPORT_TIMETABLE_TO_CALENDAR = "ETTC", _("Export Timetable to Calendar") + FRIENDS = "F", _("Friends") + ADVANCED_SEARCH = "AS", _("Advanced Search") + COURSE_OPTIMIZER = "CO", _("Course Optimizer") + + +class FeatureUse(models.Model): + """Database object containing indicators which provide information about whether + a User has used a certain feature or not + """ + user = models.OneToOneField(User, on_delete=models.deletion.CASCADE) + feature_name = models.CharField(max_length=4, choices=Feature) + time_used = models.DateTimeField(auto_now_add=True) \ No newline at end of file diff --git a/feature_use_tracker/serializers.py b/feature_use_tracker/serializers.py new file mode 100644 index 0000000000..dfe201bbe7 --- /dev/null +++ b/feature_use_tracker/serializers.py @@ -0,0 +1,8 @@ +from rest_framework import serializers +from .models import FeatureUse + +class FeatureUseSerializer(serializers.ModelSerializer): + class Meta: + model = FeatureUse + fields = ["id", "user", "feature_name", "time_used"] + read_only_fields = ["time_used"] diff --git a/feature_use_tracker/tests.py b/feature_use_tracker/tests.py new file mode 100644 index 0000000000..a57ae8ac02 --- /dev/null +++ b/feature_use_tracker/tests.py @@ -0,0 +1,15 @@ +# Copyright (C) 2017 Semester.ly Technologies, LLC +# +# Semester.ly is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Semester.ly is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +from django.test import TestCase + +# Create your tests here. diff --git a/feature_use_tracker/urls.py b/feature_use_tracker/urls.py new file mode 100644 index 0000000000..892c87ee0f --- /dev/null +++ b/feature_use_tracker/urls.py @@ -0,0 +1,7 @@ +from django.urls import re_path +from .views import FeatureUseView, csrf_cookie_view + +urlpatterns = [ + re_path(r"^feature_use/csrf/$", csrf_cookie_view, name="feature_use_get_csrf"), + re_path(r"^feature_use/$", FeatureUseView.as_view(), name="feature_use"), +] diff --git a/feature_use_tracker/views.py b/feature_use_tracker/views.py new file mode 100644 index 0000000000..d07c7c653a --- /dev/null +++ b/feature_use_tracker/views.py @@ -0,0 +1,46 @@ +# Copyright (C) 2017 Semester.ly Technologies, LLC +# +# Semester.ly is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Semester.ly is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +from rest_framework.views import APIView +from rest_framework.response import Response +from feature_use_tracker.models import FeatureUse, Feature +from feature_use_tracker.serializers import FeatureUseSerializer + + +# Create your views here. +class FeatureUseView(APIView): + """ + List relevant feature use entries (for red-dot rendering logic), or create a new entry + """ + + def post(self, request): + # drop the 'user' field if client supplies it (we only want to get User through inference) + data = request.data.copy() + data.pop("user", None) + + feature = data.get("feature_name") + + # delete duplicates if necessary + exists = FeatureUse.objects.filter(user=request.user, feature_name=feature).exists() + if exists: + return Response(status=204) + + serializer = FeatureUseSerializer(data=data) + serializer.is_valid(raise_exception=True) + serializer.save(user=request.user) + return Response(serializer.data) + + + def get(self, request): + rows = FeatureUse.objects.filter(user=request.user) + serializer = FeatureUseSerializer(rows, many=True) + return Response(serializer.data) diff --git a/semesterly/urls.py b/semesterly/urls.py index 57514f6c0e..92a4b135db 100644 --- a/semesterly/urls.py +++ b/semesterly/urls.py @@ -34,6 +34,7 @@ re_path("", include("notifications.urls")), re_path("", include("friends.urls")), re_path("", include("course_history.urls")), + re_path("", include("feature_use.urls")) re_path(r"admin/?", admin.site.urls), # Automatic deployment endpoint re_path(r"deploy_staging/?", semesterly.views.deploy_staging),