Add Login page
This commit is contained in:
parent
b1c5be61f1
commit
679414a703
34 changed files with 6545 additions and 2 deletions
3
.babelrc
Normal file
3
.babelrc
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"presets": ["@babel/preset-env"]
|
||||||
|
}
|
||||||
6
.gitignore
vendored
6
.gitignore
vendored
|
|
@ -192,3 +192,9 @@ dmypy.json
|
||||||
# Pyre type checker
|
# Pyre type checker
|
||||||
|
|
||||||
# End of https://www.gitignore.io/api/django,python
|
# End of https://www.gitignore.io/api/django,python
|
||||||
|
|
||||||
|
# Javascript
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# Css
|
||||||
|
*.css
|
||||||
|
|
|
||||||
17
gulp/sass.js
Normal file
17
gulp/sass.js
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
import { src, dest } from "gulp";
|
||||||
|
|
||||||
|
import concat from "gulp-concat";
|
||||||
|
import path from "path";
|
||||||
|
import sass from "gulp-sass";
|
||||||
|
|
||||||
|
const PROJECT_DIR = path.join("src", "newsreader");
|
||||||
|
const STATIC_DIR = path.join(PROJECT_DIR, "static");
|
||||||
|
|
||||||
|
export const ACCOUNTS_DIR = path.join(PROJECT_DIR, "accounts", "static");
|
||||||
|
|
||||||
|
export default function accountsTask(){
|
||||||
|
return src(`${STATIC_DIR}/src/scss/accounts/index.scss`)
|
||||||
|
.pipe(sass().on("error", sass.logError))
|
||||||
|
.pipe(concat("accounts.css"))
|
||||||
|
.pipe(dest(`${ACCOUNTS_DIR}/accounts/dist/css`));
|
||||||
|
};
|
||||||
22
gulpfile.babel.js
Normal file
22
gulpfile.babel.js
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
import { series, watch as _watch } from 'gulp';
|
||||||
|
|
||||||
|
import path from "path";
|
||||||
|
import del from "del";
|
||||||
|
|
||||||
|
import buildSass, { ACCOUNTS_DIR } from "./gulp/sass";
|
||||||
|
|
||||||
|
const STATIC_DIR = path.join("src", "newsreader", "static");
|
||||||
|
|
||||||
|
function clean(){
|
||||||
|
return del([
|
||||||
|
`${ACCOUNTS_DIR}/accounts/dist/css/*`,
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
|
||||||
|
export function watch(){
|
||||||
|
_watch(`${STATIC_DIR}/src/scss/**/*.scss`, (done) => {
|
||||||
|
series(clean, buildSass)(done);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export default series(clean, buildSass);
|
||||||
6189
package-lock.json
generated
Normal file
6189
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
40
package.json
Normal file
40
package.json
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
{
|
||||||
|
"name": "newsreader",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"description": "Application for viewing RSS feeds",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"lint": "prettier \"src/newsreader/**/*.js\" --check",
|
||||||
|
"format": "prettier \"src/newsreader/**/*.js\" --write"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "[git@git.fudiggity.nl:5000]:sonny/newsreader.git"
|
||||||
|
},
|
||||||
|
"author": "Sonny",
|
||||||
|
"license": "GPL-3.0-or-later",
|
||||||
|
"prettier": {
|
||||||
|
"semi": true,
|
||||||
|
"trailingComma": "es5",
|
||||||
|
"singleQuote": false,
|
||||||
|
"printWidth": 80,
|
||||||
|
"tabWidth": 2,
|
||||||
|
"useTabs": false,
|
||||||
|
"bracketSpacing": false,
|
||||||
|
"arrowParens": "always"
|
||||||
|
},
|
||||||
|
"dependencies": {},
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.5.4",
|
||||||
|
"@babel/preset-env": "^7.5.4",
|
||||||
|
"@babel/register": "^7.4.4",
|
||||||
|
"del": "^5.0.0",
|
||||||
|
"gulp": "^4.0.2",
|
||||||
|
"gulp-babel": "^8.0.0-beta.2",
|
||||||
|
"gulp-cli": "^2.2.0",
|
||||||
|
"gulp-concat": "^2.6.1",
|
||||||
|
"gulp-sass": "^4.0.2",
|
||||||
|
"node-sass": "^4.12.0",
|
||||||
|
"prettier": "^1.18.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
24
src/newsreader/accounts/templates/accounts/login.html
Normal file
24
src/newsreader/accounts/templates/accounts/login.html
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% load static %}
|
||||||
|
|
||||||
|
{% block head %}
|
||||||
|
<link href="{% static 'accounts/dist/css/accounts.css' %}" rel="stylesheet" />
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<main class="main">
|
||||||
|
<form class="login-form" method="POST" action="{% url 'accounts:login' %}">
|
||||||
|
{% csrf_token %}
|
||||||
|
<h4>Login</h4>
|
||||||
|
|
||||||
|
<fieldset class="login-form__fieldset">
|
||||||
|
{{ form }}
|
||||||
|
</fieldset>
|
||||||
|
<fieldset class="login-form__fieldset">
|
||||||
|
<button class="button button--confirm" type="submit">Login</button>
|
||||||
|
<a><small>I forgot my password</small></a>
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
|
</main>
|
||||||
|
{% endblock %}
|
||||||
9
src/newsreader/accounts/urls.py
Normal file
9
src/newsreader/accounts/urls.py
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
from django.urls import include, path
|
||||||
|
|
||||||
|
from newsreader.accounts.views import LoginView, LogoutView
|
||||||
|
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path("login/", LoginView.as_view(), name="login"),
|
||||||
|
path("logout/", LogoutView.as_view(), name="logout"),
|
||||||
|
]
|
||||||
|
|
@ -1 +1,16 @@
|
||||||
# Create your views here.
|
from django.contrib.auth.views import LoginView as DjangoLoginView
|
||||||
|
from django.contrib.auth.views import LogoutView as DjangoLogoutView
|
||||||
|
from django.urls import reverse_lazy
|
||||||
|
|
||||||
|
|
||||||
|
# TODO redirect to homepage when logged in
|
||||||
|
class LoginView(DjangoLoginView):
|
||||||
|
template_name = "accounts/login.html"
|
||||||
|
|
||||||
|
def get_success_url(self):
|
||||||
|
# TODO redirect to homepage
|
||||||
|
return reverse_lazy("admin:index")
|
||||||
|
|
||||||
|
|
||||||
|
class LogoutView(DjangoLogoutView):
|
||||||
|
next_page = reverse_lazy("accounts:login")
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ ROOT_URLCONF = "newsreader.urls"
|
||||||
TEMPLATES = [
|
TEMPLATES = [
|
||||||
{
|
{
|
||||||
"BACKEND": "django.template.backends.django.DjangoTemplates",
|
"BACKEND": "django.template.backends.django.DjangoTemplates",
|
||||||
"DIRS": [],
|
"DIRS": [os.path.join(BASE_DIR, "templates")],
|
||||||
"APP_DIRS": True,
|
"APP_DIRS": True,
|
||||||
"OPTIONS": {
|
"OPTIONS": {
|
||||||
"context_processors": [
|
"context_processors": [
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
.login-form {
|
||||||
|
@extend .form;
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
margin: 0;
|
||||||
|
padding: 20px 24px 5px 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__fieldset {
|
||||||
|
@extend .form__fieldset;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__fieldset * {
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__fieldset:last-child {
|
||||||
|
flex-direction: row-reverse;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__fieldset:last-child {
|
||||||
|
.button {
|
||||||
|
padding: 10px 50px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
@import "form";
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
@import "./main/index";
|
||||||
|
@import "./form/index";
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
.main {
|
||||||
|
@extend .main;
|
||||||
|
|
||||||
|
margin: 5% auto;
|
||||||
|
width: 50%;
|
||||||
|
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
@import "main";
|
||||||
4
src/newsreader/static/src/scss/accounts/index.scss
Normal file
4
src/newsreader/static/src/scss/accounts/index.scss
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
@import "../partials/variables";
|
||||||
|
@import "../components/index";
|
||||||
|
|
||||||
|
@import "./components/index";
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
.body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
background-color: $gainsboro;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
@import "body";
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
.button {
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
padding: 10px 50px;
|
||||||
|
|
||||||
|
width: 50px;
|
||||||
|
|
||||||
|
border: none;
|
||||||
|
border-radius: 2px;
|
||||||
|
|
||||||
|
font-family: $button-font;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--confirm {
|
||||||
|
color: $white;
|
||||||
|
background-color: $confirm-green;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: lighten($confirm-green, +5%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
@import "button";
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
%error {
|
||||||
|
background-color: $error-red;
|
||||||
|
color: $white;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
.errorlist {
|
||||||
|
@extend %error;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
@import "error";
|
||||||
|
@import "errorlist";
|
||||||
13
src/newsreader/static/src/scss/components/form/_form.scss
Normal file
13
src/newsreader/static/src/scss/components/form/_form.scss
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
.form {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
font-family: $form-font;
|
||||||
|
|
||||||
|
&__fieldset {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
@import "form";
|
||||||
6
src/newsreader/static/src/scss/components/index.scss
Normal file
6
src/newsreader/static/src/scss/components/index.scss
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
@import "./body/index";
|
||||||
|
@import "./button/index";
|
||||||
|
@import "./form/index";
|
||||||
|
@import "./main/index";
|
||||||
|
@import "./navbar/index";
|
||||||
|
@import "./error/index";
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
.main {
|
||||||
|
margin: 1% 10% 5% 10%;
|
||||||
|
background-color: $white;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
@import "main";
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
.nav {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
background-color: $white;
|
||||||
|
box-shadow: 0px 5px darken($azureish-white, +10%);
|
||||||
|
|
||||||
|
ol {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-start;
|
||||||
|
|
||||||
|
width: 80%;
|
||||||
|
list-style-type: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: $nickel;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__item {
|
||||||
|
margin: 0px 10px;
|
||||||
|
|
||||||
|
border: none;
|
||||||
|
border-radius: 2px;
|
||||||
|
|
||||||
|
background-color: $azureish-white;
|
||||||
|
|
||||||
|
&:hover{
|
||||||
|
background-color: lighten($azureish-white, +5%);
|
||||||
|
}
|
||||||
|
|
||||||
|
& a {
|
||||||
|
@extend .button;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__item:last-child {
|
||||||
|
margin: 0 10px 0 auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
@import "navbar";
|
||||||
26
src/newsreader/static/src/scss/partials/_variables.scss
Normal file
26
src/newsreader/static/src/scss/partials/_variables.scss
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
@import url("https://fonts.googleapis.com/css?family=IBM+Plex+Sans:600&display=swap");
|
||||||
|
@import url('https://fonts.googleapis.com/css?family=Barlow&display=swap');
|
||||||
|
|
||||||
|
$button-font: "IBM Plex Sans", sans-serif;
|
||||||
|
$form-font: "Barlow", sans-serif;
|
||||||
|
|
||||||
|
/* colors */
|
||||||
|
$white: rgba(255, 255, 255, 1);
|
||||||
|
|
||||||
|
$confirm-green: rgba(46,204,113, 1);
|
||||||
|
$error-red: rgba(231,76,60, 1);
|
||||||
|
|
||||||
|
// light blue
|
||||||
|
$azureish-white: rgba(205, 230, 245, 1);
|
||||||
|
|
||||||
|
// dark blue
|
||||||
|
$pewter-blue: rgba(141, 167, 190, 1);
|
||||||
|
|
||||||
|
// light gray
|
||||||
|
$gainsboro: rgba(224, 221, 220, 1);
|
||||||
|
|
||||||
|
// medium gray
|
||||||
|
$roman-silver: rgba(135, 145, 158, 1);
|
||||||
|
|
||||||
|
//dark gray
|
||||||
|
$nickel: rgba(112, 112, 120, 1);
|
||||||
33
src/newsreader/templates/base.html
Normal file
33
src/newsreader/templates/base.html
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Newreader</title>
|
||||||
|
{% block head %}{% endblock %}
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body class="body">
|
||||||
|
<nav class="nav">
|
||||||
|
<ol>
|
||||||
|
{% if request.user.is_authenticated %}
|
||||||
|
<li class="nav__item"><a href="#">Home</a></li>
|
||||||
|
<li class="nav__item"><a href="#">Settings</a></li>
|
||||||
|
<li class="nav__item"><a href="{% url 'accounts:logout' %}">Logout</a></li>
|
||||||
|
{% else %}
|
||||||
|
<li class="nav__item"><a href="{% url 'accounts:login' %}">Login</a></li>
|
||||||
|
{% endif %}
|
||||||
|
</ol>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
{% if messages %}
|
||||||
|
<ul class="messages">
|
||||||
|
{% for message in messages %}
|
||||||
|
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>
|
||||||
|
{{ message }}
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% block content %}{% endblock content %}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -2,6 +2,7 @@ from django.conf import settings
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.urls import include, path
|
from django.urls import include, path
|
||||||
|
|
||||||
|
from newsreader.accounts.urls import urlpatterns as login_urls
|
||||||
from newsreader.news.collection.urls import endpoints as collection_endpoints
|
from newsreader.news.collection.urls import endpoints as collection_endpoints
|
||||||
from newsreader.news.core.urls import endpoints as core_endpoints
|
from newsreader.news.core.urls import endpoints as core_endpoints
|
||||||
|
|
||||||
|
|
@ -9,6 +10,7 @@ from newsreader.news.core.urls import endpoints as core_endpoints
|
||||||
endpoints = collection_endpoints + core_endpoints
|
endpoints = collection_endpoints + core_endpoints
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
|
path("accounts/", include((login_urls, "accounts")), name="accounts"),
|
||||||
path("admin/", admin.site.urls, name="admin"),
|
path("admin/", admin.site.urls, name="admin"),
|
||||||
path("api/", include((endpoints, "api")), name="api"),
|
path("api/", include((endpoints, "api")), name="api"),
|
||||||
]
|
]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue