Various fixes and more imps

This commit is contained in:
Phillip Stephens
2019-07-08 18:50:45 -07:00
parent cb8668bbcc
commit 1cf4390ce7
28 changed files with 376 additions and 133 deletions
+4 -1
View File
@@ -1,9 +1,12 @@
*.pyc
*~
__pycache__
*venv*
venv
.venv
db.sqlite3
/static
/media
/martor
.DS_Store
.idea
bootstrap_autocomplete
+18 -4
View File
@@ -1,20 +1,34 @@
from django import forms
from django.contrib.auth.forms import UserCreationForm
from betterforms.multiform import MultiModelForm
from django.contrib.auth.models import User
from .models import Profile
class SignUpForm(UserCreationForm):
email = forms.CharField(max_length=254, required=True, widget=forms.EmailInput())
class UserSignUpForm(UserCreationForm):
email = forms.CharField(max_length=254, label='Email Address', required=True, widget=forms.EmailInput())
class Meta:
model = User
fields = ('username', 'email', 'password1', 'password2')
class UserProfileForm(forms.ModelForm):
class Meta:
model = Profile
fields = ['avatar', 'use_gravatar']
class UserCreationMultiForm(MultiModelForm):
form_classes = {
'user': UserSignUpForm,
'profile': UserProfileForm,
}
class ProfileForm(forms.ModelForm):
first_name = forms.CharField(max_length=256)
last_name = forms.CharField(max_length=256)
first_name = forms.CharField(max_length=256, required=False)
last_name = forms.CharField(max_length=256, required=False)
email = forms.EmailField(max_length=254, required=True, widget=forms.EmailInput())
use_gravatar = forms.BooleanField(label='Use avatars from Gravatar?', required=False)
+1 -1
View File
@@ -1,4 +1,4 @@
# Generated by Django 2.2.3 on 2019-07-07 12:44
# Generated by Django 2.2.3 on 2019-07-08 13:36
import accounts.models
from django.conf import settings
+30
View File
@@ -36,3 +36,33 @@ def create_or_update_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
instance.profile.save()
@receiver(models.signals.post_delete, sender=Profile)
def auto_delete_file_on_delete(sender, instance, **kwargs):
"""
Deletes file from filesystem
when corresponding `Profile` object is deleted.
"""
if instance.avatar:
instance.avatar.delete(save=False)
@receiver(models.signals.pre_save, sender=Profile)
def auto_delete_file_on_change(sender, instance, **kwargs):
"""
Deletes old file from filesystem
when corresponding `Profile` object is updated
with new file.
"""
if not instance.pk:
return False
try:
old_avatar = Profile.objects.get(pk=instance.pk).avatar
except Profile.DoesNotExist:
return False
new_avatar = instance.avatar
if not old_avatar == new_avatar:
old_avatar.delete(save=False)
+1 -1
View File
@@ -1,6 +1,6 @@
{% extends 'base_accounts.html' %}
{% block title %}Sign up to Django Boards{% endblock %}
{% block title %}Sign up to AxioDL{% endblock %}
{% block content %}
<div class="row justify-content-center">
+3 -2
View File
@@ -1,10 +1,10 @@
from django.conf.urls import url, include
from django.contrib.auth import views as auth_views
from .views import signup, UserUpdateView
from .views import UserUpdateView, gitlab_auth, UserSignupView
urlpatterns = [
url(r'^signup/$', signup, name='signup'),
url(r'^signup/$', UserSignupView.as_view(), name='signup'),
url(r'^login/$', auth_views.LoginView.as_view(template_name='login.html'), name='login'),
url(r'^logout/$', auth_views.LogoutView.as_view(), name='logout'),
url(r'^reset/$',
@@ -29,4 +29,5 @@ urlpatterns = [
template_name='password_change_done.html'),
name='password_change_done'),
url(r'^view/$', UserUpdateView.as_view(), name='view_account'),
url(r'^gitlab/callback/$', gitlab_auth, name='gitlab.callback')
]
+19 -12
View File
@@ -3,12 +3,18 @@ from django.contrib.auth import get_user_model
from django.contrib.auth.decorators import login_required
from django.urls import reverse_lazy
from django.utils.decorators import method_decorator
from django.views.generic import UpdateView
from django.views.generic import UpdateView, CreateView
from django.shortcuts import render, redirect
from .forms import SignUpForm, ProfileForm
from .forms import UserSignUpForm, ProfileForm, UserCreationMultiForm
from .models import Profile
def gitlab_auth(request):
print(request.POST)
return render(request, 'base.html')
def gravatar(user):
email = user.email.lower().encode('utf-8')
default = 'mm'
@@ -20,17 +26,18 @@ def gravatar(user):
return url
def signup(request):
if request.method == 'POST':
form = SignUpForm(request.POST)
if form.is_valid():
user = form.save()
auth_login(request, user)
return redirect('home')
else:
form = SignUpForm()
class UserSignupView(CreateView):
form_class = UserCreationMultiForm
success_url = reverse_lazy('home')
template_name = 'signup.html'
return render(request, 'signup.html', {'form': form})
def form_valid(self, form):
# We need to save the user before we can save the profile
user = form['user'].save()
profile = form['profile'].save(commit=False)
profile.user = user
profile.save()
return redirect(self.get_success_url())
@method_decorator(login_required, name='dispatch')
+1
View File
@@ -1,4 +1,5 @@
from django.contrib import admin
from .models import Board
admin.site.register(Board)
+1 -1
View File
@@ -1,6 +1,6 @@
from django import forms
from martor.fields import MartorFormField
from .models import Topic, Post
from .models import Topic, Post, Board
class NewTopicForm(forms.ModelForm):
+3 -1
View File
@@ -1,4 +1,4 @@
# Generated by Django 2.2.3 on 2019-07-07 12:44
# Generated by Django 2.2.3 on 2019-07-08 13:36
from django.conf import settings
from django.db import migrations, models
@@ -21,6 +21,8 @@ class Migration(migrations.Migration):
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=30, unique=True)),
('description', models.CharField(max_length=100)),
('parent', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, to='boards.Board')),
('children', models.ManyToManyField(blank=True, related_name='_board_children_+', to='boards.Board')),
],
),
migrations.CreateModel(
+5 -1
View File
@@ -7,6 +7,11 @@ from martor.models import MartorField
class Board(models.Model):
name = models.CharField(max_length=30, unique=True)
description = models.CharField(max_length=100)
parent = models.ForeignKey('self',
on_delete=models.CASCADE,
null=True,
blank=True,
parent_link=True)
def __str__(self):
return self.name
@@ -56,4 +61,3 @@ class Post(models.Model):
def __str__(self):
truncated_message = Truncator(self.message)
return truncated_message.chars(30)
+1 -1
View File
@@ -1,4 +1,4 @@
# Generated by Django 2.2.3 on 2019-07-07 12:44
# Generated by Django 2.2.3 on 2019-07-08 13:36
from django.conf import settings
from django.db import migrations, models
File diff suppressed because one or more lines are too long
+66 -69
View File
@@ -1,69 +1,66 @@
.codehilight .hll { background-color: #ffffcc }
.codehilight { background: #f8f8f8; }
.codehilight .c { color: #408080; font-style: italic } /* Comment */
.codehilight .err { border: 1px solid #FF0000 } /* Error */
.codehilight .k { color: #008000; font-weight: bold } /* Keyword */
.codehilight .o { color: #666666 } /* Operator */
.codehilight .ch { color: #408080; font-style: italic } /* Comment.Hashbang */
.codehilight .cm { color: #408080; font-style: italic } /* Comment.Multiline */
.codehilight .cp { color: #BC7A00 } /* Comment.Preproc */
.codehilight .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */
.codehilight .c1 { color: #408080; font-style: italic } /* Comment.Single */
.codehilight .cs { color: #408080; font-style: italic } /* Comment.Special */
.codehilight .gd { color: #A00000 } /* Generic.Deleted */
.codehilight .ge { font-style: italic } /* Generic.Emph */
.codehilight .gr { color: #FF0000 } /* Generic.Error */
.codehilight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
.codehilight .gi { color: #00A000 } /* Generic.Inserted */
.codehilight .go { color: #888888 } /* Generic.Output */
.codehilight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
.codehilight .gs { font-weight: bold } /* Generic.Strong */
.codehilight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.codehilight .gt { color: #0044DD } /* Generic.Traceback */
.codehilight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
.codehilight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
.codehilight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
.codehilight .kp { color: #008000 } /* Keyword.Pseudo */
.codehilight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
.codehilight .kt { color: #B00040 } /* Keyword.Type */
.codehilight .m { color: #666666 } /* Literal.Number */
.codehilight .s { color: #BA2121 } /* Literal.String */
.codehilight .na { color: #7D9029 } /* Name.Attribute */
.codehilight .nb { color: #008000 } /* Name.Builtin */
.codehilight .nc { color: #0000FF; font-weight: bold } /* Name.Class */
.codehilight .no { color: #880000 } /* Name.Constant */
.codehilight .nd { color: #AA22FF } /* Name.Decorator */
.codehilight .ni { color: #999999; font-weight: bold } /* Name.Entity */
.codehilight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
.codehilight .nf { color: #0000FF } /* Name.Function */
.codehilight .nl { color: #A0A000 } /* Name.Label */
.codehilight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
.codehilight .nt { color: #008000; font-weight: bold } /* Name.Tag */
.codehilight .nv { color: #19177C } /* Name.Variable */
.codehilight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
.codehilight .w { color: #bbbbbb } /* Text.Whitespace */
.codehilight .mb { color: #666666 } /* Literal.Number.Bin */
.codehilight .mf { color: #666666 } /* Literal.Number.Float */
.codehilight .mh { color: #666666 } /* Literal.Number.Hex */
.codehilight .mi { color: #666666 } /* Literal.Number.Integer */
.codehilight .mo { color: #666666 } /* Literal.Number.Oct */
.codehilight .sa { color: #BA2121 } /* Literal.String.Affix */
.codehilight .sb { color: #BA2121 } /* Literal.String.Backtick */
.codehilight .sc { color: #BA2121 } /* Literal.String.Char */
.codehilight .dl { color: #BA2121 } /* Literal.String.Delimiter */
.codehilight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
.codehilight .s2 { color: #BA2121 } /* Literal.String.Double */
.codehilight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
.codehilight .sh { color: #BA2121 } /* Literal.String.Heredoc */
.codehilight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
.codehilight .sx { color: #008000 } /* Literal.String.Other */
.codehilight .sr { color: #BB6688 } /* Literal.String.Regex */
.codehilight .s1 { color: #BA2121 } /* Literal.String.Single */
.codehilight .ss { color: #19177C } /* Literal.String.Symbol */
.codehilight .bp { color: #008000 } /* Name.Builtin.Pseudo */
.codehilight .fm { color: #0000FF } /* Name.Function.Magic */
.codehilight .vc { color: #19177C } /* Name.Variable.Class */
.codehilight .vg { color: #19177C } /* Name.Variable.Global */
.codehilight .vi { color: #19177C } /* Name.Variable.Instance */
.codehilight .vm { color: #19177C } /* Name.Variable.Magic */
.codehilight .il { color: #666666 } /* Literal.Number.Integer.Long */
.highlight .hll { background-color: #ffffcc }
.highlight { background: #ffffff; }
.highlight .c { color: #aaaaaa; font-style: italic } /* Comment */
.highlight .err { color: #FF0000; background-color: #FFAAAA } /* Error */
.highlight .k { color: #0000aa } /* Keyword */
.highlight .ch { color: #aaaaaa; font-style: italic } /* Comment.Hashbang */
.highlight .cm { color: #aaaaaa; font-style: italic } /* Comment.Multiline */
.highlight .cp { color: #4c8317 } /* Comment.Preproc */
.highlight .cpf { color: #aaaaaa; font-style: italic } /* Comment.PreprocFile */
.highlight .c1 { color: #aaaaaa; font-style: italic } /* Comment.Single */
.highlight .cs { color: #0000aa; font-style: italic } /* Comment.Special */
.highlight .gd { color: #aa0000 } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
.highlight .gi { color: #00aa00 } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #0000aa } /* Keyword.Constant */
.highlight .kd { color: #0000aa } /* Keyword.Declaration */
.highlight .kn { color: #0000aa } /* Keyword.Namespace */
.highlight .kp { color: #0000aa } /* Keyword.Pseudo */
.highlight .kr { color: #0000aa } /* Keyword.Reserved */
.highlight .kt { color: #00aaaa } /* Keyword.Type */
.highlight .m { color: #009999 } /* Literal.Number */
.highlight .s { color: #aa5500 } /* Literal.String */
.highlight .na { color: #1e90ff } /* Name.Attribute */
.highlight .nb { color: #00aaaa } /* Name.Builtin */
.highlight .nc { color: #00aa00; text-decoration: underline } /* Name.Class */
.highlight .no { color: #aa0000 } /* Name.Constant */
.highlight .nd { color: #888888 } /* Name.Decorator */
.highlight .ni { color: #880000; font-weight: bold } /* Name.Entity */
.highlight .nf { color: #00aa00 } /* Name.Function */
.highlight .nn { color: #00aaaa; text-decoration: underline } /* Name.Namespace */
.highlight .nt { color: #1e90ff; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #aa0000 } /* Name.Variable */
.highlight .ow { color: #0000aa } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #009999 } /* Literal.Number.Bin */
.highlight .mf { color: #009999 } /* Literal.Number.Float */
.highlight .mh { color: #009999 } /* Literal.Number.Hex */
.highlight .mi { color: #009999 } /* Literal.Number.Integer */
.highlight .mo { color: #009999 } /* Literal.Number.Oct */
.highlight .sa { color: #aa5500 } /* Literal.String.Affix */
.highlight .sb { color: #aa5500 } /* Literal.String.Backtick */
.highlight .sc { color: #aa5500 } /* Literal.String.Char */
.highlight .dl { color: #aa5500 } /* Literal.String.Delimiter */
.highlight .sd { color: #aa5500 } /* Literal.String.Doc */
.highlight .s2 { color: #aa5500 } /* Literal.String.Double */
.highlight .se { color: #aa5500 } /* Literal.String.Escape */
.highlight .sh { color: #aa5500 } /* Literal.String.Heredoc */
.highlight .si { color: #aa5500 } /* Literal.String.Interpol */
.highlight .sx { color: #aa5500 } /* Literal.String.Other */
.highlight .sr { color: #009999 } /* Literal.String.Regex */
.highlight .s1 { color: #aa5500 } /* Literal.String.Single */
.highlight .ss { color: #0000aa } /* Literal.String.Symbol */
.highlight .bp { color: #00aaaa } /* Name.Builtin.Pseudo */
.highlight .fm { color: #00aa00 } /* Name.Function.Magic */
.highlight .vc { color: #aa0000 } /* Name.Variable.Class */
.highlight .vg { color: #aa0000 } /* Name.Variable.Global */
.highlight .vi { color: #aa0000 } /* Name.Variable.Instance */
.highlight .vm { color: #aa0000 } /* Name.Variable.Magic */
.highlight .il { color: #009999 } /* Literal.Number.Integer.Long */
+19 -4
View File
@@ -4,6 +4,7 @@
<html>
<head>
<meta charset="utf-8">
{% block meta %}{% endblock %}
<title>{% block title %}Django Boards{% endblock %}</title>
<link rel="shortcut icon" href="{% static 'favicon.ico' %}">
<link href="https://fonts.googleapis.com/css?family=Peralta" rel="stylesheet">
@@ -13,7 +14,10 @@
<link href="{% static 'plugins/css/semantic.min.css' %}" type="text/css" media="all" rel="stylesheet">
<link href="{% static 'plugins/css/resizable.min.css' %}" type="text/css" media="all" rel="stylesheet">
<link href="{% static 'martor/css/martor.min.css' %}" type="text/css" media="all" rel="stylesheet">
<link href="{% static 'martor/css/martor-admin.min.css' %}" type="text/css" media="all" rel="stylesheet">
<link href="{% sass_src 'css/app.scss' %}" type="text/css" media="all" rel="stylesheet">
<link href="{% static 'css/styles.css' %}" type="text/css" media="all" rel="stylesheet">
<script type="text/javascript" src="{% static 'plugins/js/snippets/markdown.js' %}"></script>
{% block stylesheet %}{% endblock %}
</head>
<body class="d-flex flex-column">
@@ -62,6 +66,9 @@
class="btn btn-primary bg-light text-dark">Forums</a>
{% endif %}
{% endif %}
<a href="{% url 'pages.list' %}"
class="btn btn-primary bg-light text-dark">Page list</a>
</form>
{% if user.is_authenticated %}
<ul class="navbar-nav ml-auto btn btn-secondary btn-sm">
@@ -120,10 +127,18 @@
<script type="text/javascript" src="{% static 'plugins/js/mode-markdown.js' %}"></script>
<script type="text/javascript" src="{% static 'plugins/js/ext-language_tools.js' %}"></script>
<script type="text/javascript" src="{% static 'plugins/js/theme-github.js' %}"></script>
<script type="text/javascript" src="/static/plugins/js/highlight.min.js"></script>
<script type="text/javascript" src="/static/plugins/js/resizable.min.js"></script>
<script type="text/javascript" src="/static/plugins/js/emojis.min.js"></script>
<script type="text/javascript" src="/static/martor/js/martor.min.js"></script>
<script type="text/javascript" src="{% static 'plugins/js/highlight.min.js' %}"></script>
<script type="text/javascript" src="{% static 'plugins/js/resizable.min.js' %}"></script>
<script type="text/javascript" src="{% static 'plugins/js/emojis.min.js' %}"></script>
<script type="text/javascript" src="{% static 'martor/js/martor.min.js' %}"></script>
<script type="text/javascript" src="{% static 'plugins/js/semantic.min.js' %}"></script>
<script type="text/javascript" src="{% static 'plugins/js/highlight.min.js' %}"></script>
<script>
$('pre').each(function (i, block) {
hljs.highlightBlock(block);
});
$('.ui.dropdown').dropdown();
</script>
{% block javascript %}{% endblock %}
<div class="footer py-1 bg-dark text-white-50">
<div class="container text-center">
+39
View File
@@ -0,0 +1,39 @@
{% extends 'base.html' %}
{% block breadcrumb %}
<li class="breadcrumb-item"><a href="{% url 'home' %}">Index</a></li>
<li class="breadcrumb-item active">Delete page</li>
{% endblock %}
{% block content %}
<div class="row justify-content-center">
<div class="col-lg-5 col-md-6 col-sm-8">
<div class="card border-dark">
<div class="card-header bg-dark text-light">
<div class="card-title col-md-9 text-center">
Are you sure you want to delete {{ page.page_name }}?
</div>
</div>
<form method="post" novalidate>
{% csrf_token %}
{% include 'includes/form.html' %}
<div class="card-body">
<p>Deleting a page is permanent and cannot be undone. <br/>Are you sure you wish to delete the
page '{{ page.page_name }}'?</p>
</div>
<div class="card-footer bg-dark">
<div id="container-fluid">
<div class="row">
<div class="col-7"></div>
<div class="col-2 btn-group">
<a href="{{ request.META.HTTP_REFERER }}" class="btn btn-success">Cancel</a>
<button type="submit" class="btn btn-danger">Delete</button>
</div>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
{% endblock %}
+57
View File
@@ -0,0 +1,57 @@
{% extends 'base.html' %}
{% block breadcrumb %}
<li class="breadcrumb-item"><a href="{% url 'home' %}">Index</a></li>
<li class="breadcrumb-item active">Page list</li>
{% endblock %}
{% block content %}
<table class="table bg-light">
<thead class="thead-dark">
<tr>
<th>Logo</th>
<th>Title</th>
<th>Main Page</th>
<th>Description</th>
<th>URL</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for page in pages %}
<tr>
<td>
<img src="{{ page.logo.url }}" width="24px"/>
</td>
<td class="align-middle">
{{ page.page_name }}
</td>
<td class="align-middle">
{{ page.is_mainpage|yesno:"Yes,No" }}
</td>
<td class="align-middle">
{{ page.description }}
</td>
<td class="align-middle">
<a href='{% url 'pages.view.page' page.slug %}'> {% url 'pages.view.page' page.slug %}</a>
</td>
<td>
{% if perms.pages.delete_page or perms.pages.edit_page %}
<div class="btn-group">
{% if perms.pages.delete_page %}
<a href="{% url 'pages.delete.page' page.slug %}"
class="btn btn-danger confirm-delete">Delete</a>
{% endif %}
{% if perms.pages.edit_page %}
<a href="{% url 'pages.edit.page' page.slug %}"
class="btn btn-primary">Edit</a>
{% endif %}
</div>
{% else %}
None
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
+5 -10
View File
@@ -3,14 +3,9 @@
{% load martortags %}
{% load page_extras %}
{% block javascript %}
<script>
$(document).on('click', '.confirm-delete', function () {
return confirm('Are you sure you want to delete this?');
})
</script>
{% block meta %}
{{ page|generate_twitter_card }}
{% endblock %}
{% block breadcrumb-base %}<br/>{% endblock %}
{% block content %}
{% if page %}
@@ -18,12 +13,12 @@
<div class="card-header bg-dark border-dark text-light">
<div class="row">
<div class="col-md-1">
<div class="imgAbt">
<div>
<img width="32px" src="{{ page.logo.url }}"/>
</div>
</div>
<div class="col-md-9 text-center">
<h1>{{ page.page_name }}</h1>
<h2>{{ page.page_name }}</h2>
</div>
</div>
</div>
@@ -44,7 +39,7 @@
<div class="col-2 text-center">
<!-- spacer -->
</div>
<div class="col-2 btn-group">
<div class="btn-group">
{% if perms.pages.delete_page %}
<a href="{% url 'pages.delete.page' page.slug %}"
class="btn btn-danger confirm-delete">Delete</a>

Some files were not shown because too many files have changed in this diff Show More