Skip to content

Users black dashboard #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Mar 16, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"plugins": ["@babel/plugin-syntax-dynamic-import"]
}
4 changes: 4 additions & 0 deletions TODO
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Idea: Start new users with demo data and little popups. When they enter their first entry, popup about deleting their demo data. And have message "When you're ready to start tracking your own data, CLICK HERE to delete data"


Users should be able to edit their (add / delete) categories at their whim. More complicated with entries in a category though.
4 changes: 2 additions & 2 deletions app.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "Django VueJs Template",
"name": "Docker Django VueJs Postgres Template",
"description": "",
"repository": "https://github.com/gtalarico/django-vue-template",
"repository": "https://github.com/iprogramstuff/docker-django-vue-postgres-template",
"keywords": ["django", "vue", "vuejs", "template", "django rest framework"],
"env": {
"DJANGO_SETTINGS_MODULE": {
Expand Down
25 changes: 25 additions & 0 deletions backend/api/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from django.urls import path, include
# from django.contrib.auth.views import logout

from rest_framework_jwt.views import obtain_jwt_token, refresh_jwt_token, verify_jwt_token
from rest_framework import routers
from . import views

router = routers.DefaultRouter()
# router.register('messages', views.MessageViewSet)

# router.register('users', views.UserViewSet)

router.register('entries', views.EntryViewSet)

urlpatterns = [
path('', include(router.urls)),
path('auth/login/', obtain_jwt_token, name="auth-login"),
# path('auth/logout/', logout, name="auth-logout"),
path('auth/register/', views.CreateUserView.as_view(), name="auth-register"),
path('auth/token-refresh/', refresh_jwt_token),
path('auth/token-verify/', verify_jwt_token),
# path('auth/validate-activation-code/$', views.ValidateActivationCode.as_view(), name="validate-activation-code"),
# path('auth/change-password/$', views.ChangePasswordView.as_view(), name="change-password"),
# path('auth/forgot-password/$', views.ForgotPasswordView.as_view(), name="forgot-password"),
]
212 changes: 204 additions & 8 deletions backend/api/views.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,214 @@
from django.views.generic import TemplateView
from django.views.decorators.cache import never_cache
from rest_framework import viewsets
from django.contrib.auth import get_user_model

from rest_framework import viewsets, status, permissions
from rest_framework.response import Response
from rest_framework.generics import CreateAPIView

from .models import Message, MessageSerializer

from backend.users.models import User
from backend.users.serializers import UserSerializer

from backend.bookkeeping.models import Entry
from backend.bookkeeping.serializers import EntrySerializer


# Serve Vue Application
index_view = never_cache(TemplateView.as_view(template_name='index.html'))
appjs_view = never_cache(TemplateView.as_view(template_name='app.js'))
# class MessageViewSet(viewsets.ModelViewSet):
# """
# API endpoint that allows messages to be viewed or edited.
# """
# queryset = Message.objects.all()
# serializer_class = MessageSerializer


class MessageViewSet(viewsets.ModelViewSet):
class EntryViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows messages to be viewed or edited.
API endpoint that allows entries to be viewed or edited.
"""
queryset = Message.objects.all()
serializer_class = MessageSerializer
queryset = Entry.objects.all()
serializer_class = EntrySerializer

def perform_create(self, serializer):
return serializer.save(user=self.request.user)

class CreateUserView(CreateAPIView):
model = get_user_model()
permission_classes = [
permissions.AllowAny # Or anon users can't register
]
serializer_class = UserSerializer


# class UserViewSet(viewsets.ModelViewSet):
# # lookup_field = 'id'
# queryset = User.objects.all()
# serializer_class = UserSerializer

# def list(self, request):
# """
# List all users in database.

# returns:
# - application/json
# """
# return Response({})

# def retrieve(self, request, id=None):
# """
# Returns data on a particular user.

# returns:
# - application/json
# """
# # queryset = User.objects.all()
# # user = get_object_or_404(queryset, id=id)
# # serializer = UserSerializer(user)
# # return Response(serializer.data)
# return Response({})

# # def create(self, request):
# # """
# # Create a new user.

# # returns:
# # - application/json
# # """
# # serializer = self.serializer_class(data=request.data)

# # if serializer.is_valid():
# # user = User.objects.create_user(**serializer.validated_data)
# # new_user = User.objects.get(id=user.id)
# # new_user.sex = serializer.validated_data.get('sex', None)
# # new_user.age = serializer.validated_data.get('age', None)
# # new_user.terms_agreement = serializer.validated_data['terms_agreement']
# # new_user.loyalty_agreement = serializer.validated_data['terms_agreement']
# # new_user.verified = serializer.validated_data['verified']
# # # new_user.user_type = serializer.validated_data.get('user_type', None)
# # new_user.status = serializer.validated_data.get('status', User.STATUS_CHOICE[0][0])

# # new_user.save()

# # user_serialized_data = UserSerializer(new_user).data

# # token = generate_token(new_user)

# # # if new_user.user_type is not User.USER_TYPE_CHOICE[0][0]:
# # # tasks.send_welcome_email_task.delay(user.email,
# # # "Thank you for using signing up")
# # return Response({"user": user_serialized_data,
# # "token": token},
# # status=status.HTTP_201_CREATED)
# # else:
# # return Response({
# # 'status': 'Bad request',
# # 'errors': serializer.errors
# # }, status=status.HTTP_400_BAD_REQUEST)

# # def update(self, request, id=None):
# # """
# # Update the information of a user.

# # returns:
# # - application/json
# # """
# # user = User.objects.get(id=request.user.id)
# # serializer = UserSerializer(user, data=request.data, partial=True)

# # if serializer.is_valid():
# # new_user = serializer.save()
# # token = generate_token(new_user)

# # return Response({"user": UserSerializer(new_user).data,
# # "token": token},
# # status=status.HTTP_200_OK)

# # return Response({
# # 'status': 'Bad request',
# # 'errors': serializer.errors
# # }, status=status.HTTP_400_BAD_REQUEST)

# class ChangePasswordView(generics.UpdateAPIView):
# """
# Allows the user to change his or her password.
# """
# serializer_class = ChangePasswordSerializer
# model = User

# def get_object(self, queryset=None):
# obj = self.request.user
# return obj

# def update(self, request, *args, **kwargs):
# """
# Allows the user to update his or her password.
# """
# self.object = self.get_object()
# serializer = self.get_serializer(data=request.data)

# if serializer.is_valid():
# # Check old password
# if not self.object.check_password(serializer.data.get("old_password")):
# return Response({"old_password": ["Wrong password."]},
# status=status.HTTP_400_BAD_REQUEST)

# # set_password also hashes the password that the user will get
# self.object.set_password(serializer.data.get("password"))
# self.object.save()

# token = generate_token(self.object)

# return Response({"user": UserSerializer(self.object).data, "token": token},
# status=status.HTTP_200_OK)

# return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


# class ForgotPasswordView(views.APIView):
# renderer_classes = (renderers.JSONRenderer,)

# def get_permissions(self):
# if self.request.method in permissions.SAFE_METHODS:
# return (permissions.AllowAny(),)

# if self.request.method == 'POST':
# return (permissions.AllowAny(),)

# return (permissions.IsAuthenticated(),)

# def post(self, request, *args, **kw):
# """
# Allows the user to reset his or her password by inputing the user's email address.

# parameters:
# - email:
# - description: user's email address
# - required: true
# - paramType: form
# - type: str
# returns:
# - application/json
# """
# try:
# email = request.data['email']
# validators.validate_email(email)
# user = User.objects.get(email=email)

# if user:
# activation_code = hashlib.md5(
# settings.SECRET_KEY + email).hexdigest()
# action_url = "http://" + request.get_host() + "/forgot-password/" + \
# activation_code

# user.activation_code = activation_code
# user.save()

# tasks.ac_contact_send_reset_password_email(
# user.active_campaign_id, action_url)

# return Response({"status": "success"}, status=status.HTTP_200_OK)
# else:
# return Response({"status": "error", "message": "We could not recognize your email"}, status=status.HTTP_400_BAD_REQUEST)
# except (User.DoesNotExist, ValidationError) as e:
# return Response({"status": "error", "message": "Your email is not valid"}, status=status.HTTP_400_BAD_REQUEST)
Empty file added backend/bookkeeping/__init__.py
Empty file.
22 changes: 22 additions & 0 deletions backend/bookkeeping/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from django.contrib import admin

from . import models
# Register your models here.


class EntryAdminView(admin.ModelAdmin):
list_display = ('user', 'amount', 'notes', 'category', 'type', 'date', 'created_at')
# raw_id_fields = ("user",)
search_fields = ('user__email','user__username', 'amount', 'notes','category','type','date')


class EntryCategoryAdminView(admin.ModelAdmin):
list_display = ('id', 'name', 'type')
ordering = ('name', 'type')


admin.site.register(models.Asset)
admin.site.register(models.Liability)
admin.site.register(models.Equity)
admin.site.register(models.Entry, EntryAdminView)
admin.site.register(models.EntryCategory, EntryCategoryAdminView)
5 changes: 5 additions & 0 deletions backend/bookkeeping/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from django.apps import AppConfig


class BookkeepingConfig(AppConfig):
name = 'bookkeeping'
1 change: 1 addition & 0 deletions backend/bookkeeping/fixtures/categories.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[{"model": "bookkeeping.entrycategory", "pk": 1, "fields": {"name": "Employment", "type": 1}}, {"model": "bookkeeping.entrycategory", "pk": 2, "fields": {"name": "Rent", "type": 0}}, {"model": "bookkeeping.entrycategory", "pk": 3, "fields": {"name": "Internet", "type": 0}}, {"model": "bookkeeping.entrycategory", "pk": 4, "fields": {"name": "Hydro", "type": 0}}, {"model": "bookkeeping.entrycategory", "pk": 5, "fields": {"name": "Gas", "type": 0}}, {"model": "bookkeeping.entrycategory", "pk": 6, "fields": {"name": "Household Items", "type": 0}}, {"model": "bookkeeping.entrycategory", "pk": 7, "fields": {"name": "Groceries", "type": 0}}, {"model": "bookkeeping.entrycategory", "pk": 8, "fields": {"name": "Eating Out", "type": 0}}, {"model": "bookkeeping.entrycategory", "pk": 9, "fields": {"name": "Recreational", "type": 0}}, {"model": "bookkeeping.entrycategory", "pk": 10, "fields": {"name": "Transportation", "type": 0}}, {"model": "bookkeeping.entrycategory", "pk": 11, "fields": {"name": "Entertainment", "type": 0}}, {"model": "bookkeeping.entrycategory", "pk": 12, "fields": {"name": "Cell Phone", "type": 0}}, {"model": "bookkeeping.entrycategory", "pk": 13, "fields": {"name": "Gifts", "type": 0}}, {"model": "bookkeeping.entrycategory", "pk": 14, "fields": {"name": "Fees [Bank, etc]", "type": 0}}, {"model": "bookkeeping.entrycategory", "pk": 15, "fields": {"name": "Freelance expenses, hosting, etc", "type": 0}}, {"model": "bookkeeping.entrycategory", "pk": 16, "fields": {"name": "Hobbies", "type": 0}}, {"model": "bookkeeping.entrycategory", "pk": 17, "fields": {"name": "Other", "type": 0}}, {"model": "bookkeeping.entrycategory", "pk": 18, "fields": {"name": "Freelancing", "type": 1}}, {"model": "bookkeeping.entrycategory", "pk": 19, "fields": {"name": "Other", "type": 1}}]
85 changes: 85 additions & 0 deletions backend/bookkeeping/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# Generated by Django 2.1.7 on 2019-03-14 23:51

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

initial = True

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]

operations = [
migrations.CreateModel(
name='Asset',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('amount', models.FloatField()),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
name='Entry',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('amount', models.FloatField()),
('date', models.DateField(auto_now=True)),
('notes', models.CharField(max_length=1000)),
('type', models.IntegerField(choices=[(0, 'Expense'), (1, 'Income')])),
],
options={
'verbose_name': 'Entry',
'verbose_name_plural': 'Entries',
},
),
migrations.CreateModel(
name='EntryCategory',
fields=[
('id', models.AutoField(primary_key=True, serialize=False)),
('name', models.CharField(max_length=200)),
('type', models.IntegerField(choices=[(0, 'Expense'), (1, 'Income')])),
],
options={
'verbose_name': 'Entry Category',
'verbose_name_plural': 'Entry Categories',
},
),
migrations.CreateModel(
name='Equity',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('amount', models.FloatField()),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
options={
'verbose_name': 'Entry',
'verbose_name_plural': 'Equities',
},
),
migrations.CreateModel(
name='Liability',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('amount', models.FloatField()),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
options={
'verbose_name': 'Liablility',
'verbose_name_plural': 'Liabilities',
},
),
migrations.AddField(
model_name='entry',
name='category',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='bookkeeping.EntryCategory'),
),
migrations.AddField(
model_name='entry',
name='user',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
),
]
Loading