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
|
||||
|
||||
# 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 = [
|
||||
{
|
||||
"BACKEND": "django.template.backends.django.DjangoTemplates",
|
||||
"DIRS": [],
|
||||
"DIRS": [os.path.join(BASE_DIR, "templates")],
|
||||
"APP_DIRS": True,
|
||||
"OPTIONS": {
|
||||
"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.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.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
|
||||
|
||||
urlpatterns = [
|
||||
path("accounts/", include((login_urls, "accounts")), name="accounts"),
|
||||
path("admin/", admin.site.urls, name="admin"),
|
||||
path("api/", include((endpoints, "api")), name="api"),
|
||||
]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue