Compare commits
10 Commits
b3d5853867
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| b622fd4121 | |||
| 788eb99dcd | |||
| dcf99e5409 | |||
| cf8885ed14 | |||
| e04e991cfa | |||
| b46ec965e1 | |||
| 0793242dfe | |||
| da85e74860 | |||
| 567226684d | |||
| 1154b14e62 |
8
.gitignore
vendored
8
.gitignore
vendored
@@ -135,4 +135,10 @@ dmypy.json
|
|||||||
.pytype/
|
.pytype/
|
||||||
|
|
||||||
# Cython debug symbols
|
# Cython debug symbols
|
||||||
cython_debug/
|
cython_debug/
|
||||||
|
|
||||||
|
# npm
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# vscode
|
||||||
|
.vscode
|
||||||
0
apiv1/__init__.py
Normal file
0
apiv1/__init__.py
Normal file
3
apiv1/admin.py
Normal file
3
apiv1/admin.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
# Register your models here.
|
||||||
5
apiv1/apps.py
Normal file
5
apiv1/apps.py
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class Apiv1Config(AppConfig):
|
||||||
|
name = 'apiv1'
|
||||||
0
apiv1/migrations/__init__.py
Normal file
0
apiv1/migrations/__init__.py
Normal file
7
apiv1/models.py
Normal file
7
apiv1/models.py
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
from rest_framework import serializers
|
||||||
|
from bookmarks.models import Bookmark
|
||||||
|
|
||||||
|
class BookmarkSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Bookmark
|
||||||
|
fields = ['title', 'url', 'id']
|
||||||
3
apiv1/tests.py
Normal file
3
apiv1/tests.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
||||||
15
apiv1/urls.py
Normal file
15
apiv1/urls.py
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
from django.urls import include, path
|
||||||
|
from rest_framework import routers, authtoken
|
||||||
|
from rest_framework.authtoken import views as authtokenviews
|
||||||
|
from . import views
|
||||||
|
|
||||||
|
router = routers.DefaultRouter()
|
||||||
|
router.register(r'bookmarks', views.BookmarkViewSet, basename='bookmark')
|
||||||
|
|
||||||
|
# Wire up our API using automatic URL routing.
|
||||||
|
# Additionally, we include login URLs for the browsable API.
|
||||||
|
urlpatterns = [
|
||||||
|
path('', include(router.urls)),
|
||||||
|
path('api-auth/', include('rest_framework.urls', namespace='rest_framework')),
|
||||||
|
path('token/', authtokenviews.obtain_auth_token),
|
||||||
|
]
|
||||||
13
apiv1/views.py
Normal file
13
apiv1/views.py
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
from rest_framework import viewsets
|
||||||
|
|
||||||
|
from . import models
|
||||||
|
from bookmarks.models import Bookmark
|
||||||
|
|
||||||
|
class BookmarkViewSet(viewsets.ModelViewSet):
|
||||||
|
serializer_class = models.BookmarkSerializer
|
||||||
|
|
||||||
|
def perform_create(self, serializer):
|
||||||
|
serializer.save(user = self.request.user)
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
return Bookmark.objects.filter(user=self.request.user)
|
||||||
6
bookmarks/templates/bookmarks/bookmark_form.html
Normal file
6
bookmarks/templates/bookmarks/bookmark_form.html
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<h1>Add a bookmark</h1>
|
||||||
|
<form method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
{{ form.as_p }}
|
||||||
|
<input type="submit" value="Save">
|
||||||
|
</form>
|
||||||
@@ -4,5 +4,6 @@ from . import views
|
|||||||
|
|
||||||
app_name = 'bookmarks'
|
app_name = 'bookmarks'
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('', views.BookmarkListView.as_view(), name='bookmark-list')
|
path('', views.BookmarkListView.as_view(), name='bookmark-list'),
|
||||||
|
path('create', views.BookmarkCreate.as_view(), name='bookmark-create')
|
||||||
]
|
]
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
from django.utils import timezone
|
from .models import Bookmark
|
||||||
|
from django.urls import reverse_lazy
|
||||||
from django.views.generic.list import ListView
|
from django.views.generic.list import ListView
|
||||||
|
from django.views.generic import CreateView
|
||||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
|
|
||||||
from .models import Bookmark
|
from .models import Bookmark
|
||||||
@@ -8,7 +10,14 @@ class BookmarkListView(LoginRequiredMixin, ListView):
|
|||||||
model = Bookmark
|
model = Bookmark
|
||||||
paginate_by = 20
|
paginate_by = 20
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_queryset(self):
|
||||||
context = super().get_context_data(**kwargs)
|
return Bookmark.objects.filter(user_id=self.request.user.id)
|
||||||
context['now'] = timezone.now()
|
|
||||||
return context
|
class BookmarkCreate(LoginRequiredMixin, CreateView):
|
||||||
|
model = Bookmark
|
||||||
|
fields = ['title','url']
|
||||||
|
success_url = reverse_lazy('bookmarks:bookmark-list')
|
||||||
|
|
||||||
|
def form_valid(self, form):
|
||||||
|
form.instance.user = self.request.user
|
||||||
|
return super().form_valid(form)
|
||||||
|
|||||||
3
forgetmenot/frontend/styles.scss
Normal file
3
forgetmenot/frontend/styles.scss
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
body {
|
||||||
|
background-color: black;
|
||||||
|
}
|
||||||
@@ -32,12 +32,15 @@ ALLOWED_HOSTS = []
|
|||||||
|
|
||||||
INSTALLED_APPS = [
|
INSTALLED_APPS = [
|
||||||
'bookmarks.apps.BookmarksConfig',
|
'bookmarks.apps.BookmarksConfig',
|
||||||
|
'apiv1.apps.Apiv1Config',
|
||||||
'django.contrib.admin',
|
'django.contrib.admin',
|
||||||
'django.contrib.auth',
|
'django.contrib.auth',
|
||||||
'django.contrib.contenttypes',
|
'django.contrib.contenttypes',
|
||||||
'django.contrib.sessions',
|
'django.contrib.sessions',
|
||||||
'django.contrib.messages',
|
'django.contrib.messages',
|
||||||
'django.contrib.staticfiles',
|
'django.contrib.staticfiles',
|
||||||
|
'rest_framework',
|
||||||
|
'rest_framework.authtoken'
|
||||||
]
|
]
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
@@ -121,3 +124,17 @@ USE_TZ = True
|
|||||||
# https://docs.djangoproject.com/en/3.1/howto/static-files/
|
# https://docs.djangoproject.com/en/3.1/howto/static-files/
|
||||||
|
|
||||||
STATIC_URL = '/static/'
|
STATIC_URL = '/static/'
|
||||||
|
|
||||||
|
REST_FRAMEWORK = {
|
||||||
|
# Use Django's standard `django.contrib.auth` permissions,
|
||||||
|
# or allow read-only access for unauthenticated users.
|
||||||
|
'DEFAULT_PERMISSION_CLASSES': [
|
||||||
|
'rest_framework.permissions.IsAuthenticated'
|
||||||
|
],
|
||||||
|
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
|
||||||
|
'PAGE_SIZE': 100,
|
||||||
|
'DEFAULT_AUTHENTICATION_CLASSES': [
|
||||||
|
'rest_framework.authentication.TokenAuthentication',
|
||||||
|
'rest_framework.authentication.SessionAuthentication',
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Forget me not</title>
|
<title>Forget me not</title>
|
||||||
|
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
{% block content %} {% endblock %}
|
{% block content %} {% endblock %}
|
||||||
|
|||||||
@@ -22,5 +22,6 @@ urlpatterns = [
|
|||||||
path('', views.home, name='home'),
|
path('', views.home, name='home'),
|
||||||
path('bookmarks/', include('bookmarks.urls')),
|
path('bookmarks/', include('bookmarks.urls')),
|
||||||
path('admin/', admin.site.urls),
|
path('admin/', admin.site.urls),
|
||||||
path('accounts/', include('django.contrib.auth.urls'))
|
path('accounts/', include('django.contrib.auth.urls')),
|
||||||
|
path('api/v1/', include('apiv1.urls')),
|
||||||
]
|
]
|
||||||
|
|||||||
5130
frontend/package-lock.json
generated
Normal file
5130
frontend/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
30
frontend/package.json
Normal file
30
frontend/package.json
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
{
|
||||||
|
"name": "frontend",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
|
"watch": "webpack --watch",
|
||||||
|
"start": "webpack serve --open",
|
||||||
|
"build": "webpack --env production"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"devDependencies": {
|
||||||
|
"css-loader": "^5.2.0",
|
||||||
|
"html-webpack-plugin": "^5.3.1",
|
||||||
|
"mini-css-extract-plugin": "^1.5.1",
|
||||||
|
"sass": "^1.32.12",
|
||||||
|
"sass-loader": "^11.0.1",
|
||||||
|
"style-loader": "^2.0.0",
|
||||||
|
"webpack": "^5.31.0",
|
||||||
|
"webpack-cli": "^4.6.0",
|
||||||
|
"webpack-dev-middleware": "^4.1.0",
|
||||||
|
"webpack-dev-server": "^3.11.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"lodash": "^4.17.21"
|
||||||
|
}
|
||||||
|
}
|
||||||
1
frontend/src/styles.scss
Normal file
1
frontend/src/styles.scss
Normal file
@@ -0,0 +1 @@
|
|||||||
|
@import '../../forgetmenot/frontend/styles.scss';
|
||||||
50
frontend/webpack.config.js
Normal file
50
frontend/webpack.config.js
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
const path = require("path");
|
||||||
|
const HtmlWebpackPlugin = require("html-webpack-plugin");
|
||||||
|
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
|
||||||
|
|
||||||
|
module.exports = (env) => {
|
||||||
|
return {
|
||||||
|
mode: env.production ? "production" : "development",
|
||||||
|
entry: "./src/styles.scss",
|
||||||
|
devtool: "inline-source-map",
|
||||||
|
devServer: {
|
||||||
|
contentBase: "./dist",
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
new HtmlWebpackPlugin({
|
||||||
|
title: "Caching",
|
||||||
|
}),
|
||||||
|
new MiniCssExtractPlugin({
|
||||||
|
filename: "[name].css",
|
||||||
|
chunkFilename: "[id].css",
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
output: {
|
||||||
|
filename: "[name].[contenthash].js",
|
||||||
|
path: path.resolve(__dirname, "dist"),
|
||||||
|
clean: true,
|
||||||
|
publicPath: "/",
|
||||||
|
},
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.s[ac]ss/i,
|
||||||
|
use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
optimization: {
|
||||||
|
moduleIds: "deterministic",
|
||||||
|
runtimeChunk: "single",
|
||||||
|
splitChunks: {
|
||||||
|
cacheGroups: {
|
||||||
|
vendor: {
|
||||||
|
test: /[\\/]node_modules[\\/]/,
|
||||||
|
name: "vendors",
|
||||||
|
chunks: "all",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
BIN
requirements.txt
BIN
requirements.txt
Binary file not shown.
Reference in New Issue
Block a user