Skip to content

Commit

Permalink
Merge pull request #29 from AU-Biocommons/dev
Browse files Browse the repository at this point in the history
Add Google analytics tag
  • Loading branch information
neoformit authored Apr 10, 2024
2 parents 037bea5 + 5120964 commit e71aa50
Show file tree
Hide file tree
Showing 22 changed files with 643 additions and 8 deletions.
36 changes: 34 additions & 2 deletions app/home/admin.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
"""Define Django admin configuration for models."""

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin

from .admin_forms import UserCreationForm, UserChangeForm
from .models import User
from .admin_forms import NoticeAdminForm, UserCreationForm, UserChangeForm
from .models import User, Notice


class UserAdmin(BaseUserAdmin):
Expand Down Expand Up @@ -53,4 +55,34 @@ class UserAdmin(BaseUserAdmin):
filter_horizontal = ()


class NoticeAdmin(admin.ModelAdmin):
"""Administer notices."""

form = NoticeAdminForm

class Media:
"""Assets for the admin page."""

js = (
'//cdn.jsdelivr.net/simplemde/latest/simplemde.min.js',
'home/js/admin-required-fields.js',
'home/js/admin-mde.js',
)
css = {
'screen': (
'//cdn.jsdelivr.net/simplemde/latest/simplemde.min.css',
'home/css/admin-mde.css',
),
}

list_display = [
'datetime_modified',
'__str__',
'enabled',
'is_published',
]
order = ('-datetime_modified',)


admin.site.register(User, UserAdmin)
admin.site.register(Notice, NoticeAdmin)
36 changes: 35 additions & 1 deletion app/home/admin_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from django.contrib.auth.forms import ReadOnlyPasswordHashField
from django.core.exceptions import ValidationError

from .models import User
from .models import User, Notice


class UserCreationForm(forms.ModelForm):
Expand Down Expand Up @@ -80,3 +80,37 @@ def save(self, commit=True):
if commit:
user.save()
return user


class NoticeAdminForm(forms.ModelForm):
"""Update and create Notices.
Make the body widget bigger.
"""

class Meta:
"""Form metadata."""

model = Notice
widgets = {
'body_markdown': forms.Textarea(attrs={
'rows': 30,
'cols': 120,
}),
}
fields = '__all__'

def clean_title_html(self):
"""Clean short description."""
title = self.cleaned_data['title_html']
if not title:
return title
if '</a>' in title:
self.add_error(
'title_html',
(
'Please remove <a> tags as this creates a confusing user'
' experience (link within link).'
),
)
return title
69 changes: 69 additions & 0 deletions app/home/help_text.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
"""Help text for model fields."""

MARKDOWN_HELP_TEXT = (
"""Enter valid GitHub markdown -
<a href="https://docs.github.com/en/github/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax" target="_blank">see markdown guide</a>.
We're using <b>"code-friendly" mode</b>, so __ and _ will be rendered
literally! Use * and ** for italics/bold instead. HTML is also fine.
"""
)


class Notice:
"""Help text for Notice model fields."""

NOTICE_CLASS = """
<ul style='margin-left: 2rem;'>
<li style='list-style: disc;'>
A style class to set a color scheme for the notice - uses
<a
href='https://getbootstrap.com/docs/5.0/components/alerts/'
target='_blank'
>standard bootstrap styling</a>
(<em>info</em>: blue, <em>warning</em>: orange).
</li>
</ul>
"""

TITLE = """
<ul style='margin-left: 2rem;'>
<li style='list-style: disc;'>
This will be displayed on the landing page (200 char max) as plain
text or inline HTML (e.g.
<code>&lt;em&gt;</code>,
<code>&lt;b&gt;</code>
tags).
</li>
<li style='list-style: disc;'>
No <code>&lt;a&gt;</code> tags please, as this creates a confusing
user experience (link within link).
</li>
<li style='list-style: disc;'>
This will be shown as a single line of text above the navbar,
<b>which will be cut off if too long</b>,
especially on small screens! Please check the length is reasonable
before publishing the notice.
</li>
</ul>
"""

BODY = f"""
<ul style='margin-left: 2rem;'>
<li style='list-style: disc;'>
{MARKDOWN_HELP_TEXT}
</li>
<li style='list-style: disc;'>
<b>This text will be displayed on a dedicated webpage</b>
that is linked to from the landing page notice.
If this field is left blank, there will be no link.
</li>
</ul>
"""

MATERIAL_ICON = """
Optional. A valid Material Design icon ID to be displayed with the title
(e.g. <em>check_box</em>).
<a href="https://fonts.google.com/icons" target="_blank">
Browse 2500+ icons here
</a>.
"""
26 changes: 26 additions & 0 deletions app/home/migrations/0003_notice.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Generated by Django 4.2 on 2024-02-14 02:42

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('home', '0002_alter_user_managers'),
]

operations = [
migrations.CreateModel(
name='Notice',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('datetime_modified', models.DateTimeField(auto_now=True)),
('notice_class', models.CharField(choices=[('info', 'info'), ('warning', 'warning')], default='', help_text="\n <ul style='margin-left: 2rem;'>\n <li style='list-style: disc;'>\n A style class to set a color scheme for the notice - uses\n <a\n href='https://getbootstrap.com/docs/5.0/components/alerts/'\n target='_blank'\n >standard bootstrap styling</a>\n (<em>info</em>: blue, <em>warning</em>: orange).\n </li>\n </ul>\n ", max_length=16)),
('title_html', models.CharField(blank=True, help_text="\n <ul style='margin-left: 2rem;'>\n <li style='list-style: disc;'>\n This will be displayed on the landing page (200 char max) as plain\n text or inline HTML (e.g.\n <code>&lt;em&gt;</code>,\n <code>&lt;b&gt;</code>\n tags).\n </li>\n <li style='list-style: disc;'>\n No <code>&lt;a&gt;</code> tags please, as this creates a confusing\n user experience (link within link).\n </li>\n <li style='list-style: disc;'>\n This will be shown as a single line of text above the navbar,\n <b>which will be cut off if too long</b>,\n especially on small screens! Please check the length is reasonable\n before publishing the notice.\n </li>\n </ul>\n ", max_length=150, null=True)),
('body_markdown', models.CharField(blank=True, help_text='\n <ul style=\'margin-left: 2rem;\'>\n <li style=\'list-style: disc;\'>\n Enter valid GitHub markdown -\n <a href="https://docs.github.com/en/github/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax" target="_blank">see markdown guide</a>.\n We\'re using <b>"code-friendly" mode</b>, so __ and _ will be rendered\n literally! Use * and ** for italics/bold instead. HTML is also fine.\n \n </li>\n <li style=\'list-style: disc;\'>\n <b>This text will be displayed on a dedicated webpage</b>\n that is linked to from the landing page notice.\n If this field is left blank, there will be no link.\n </li>\n </ul>\n ', max_length=10000, null=True)),
('material_icon', models.CharField(blank=True, help_text='\n Optional. A valid Material Design icon ID to be displayed with the title\n (e.g. <em>check_box</em>).\n <a href="https://fonts.google.com/icons" target="_blank">\n Browse 2500+ icons here\n </a>.\n ', max_length=50, null=True)),
('enabled', models.BooleanField(default=False, help_text='Display on the portal landing page.')),
('is_published', models.BooleanField(default=False, help_text='Unpublished content is visible to admin users only. Use this to review content before release to public users.')),
],
),
]
72 changes: 72 additions & 0 deletions app/home/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

from django.db import models
from django.contrib.auth.models import AbstractUser

from .managers import CustomUserManager
from . import help_text


class User(AbstractUser):
Expand All @@ -20,3 +22,73 @@ class User(AbstractUser):
def __str__(self):
"""Return a string representation of self."""
return f"{self.first_name} {self.last_name} <{self.email}>"


class Notice(models.Model):
"""A site notice to be displayed on the home/landing pages.
A notice contains a brief message for display on the home page, and a
longer message that will be linked to on a separate page.
All notices will shown as rotating - displayed in a top banner and cycled
through by fade in/out such that multiple notices can be displayed without
clogging up the UI.
"""

NOTICE_CLASSES = (
('info', 'info'),
('warning', 'warning'),
)

datetime_modified = models.DateTimeField(auto_now=True)
notice_class = models.CharField(
max_length=16, choices=NOTICE_CLASSES, default='',
help_text=help_text.Notice.NOTICE_CLASS,
)
title_html = models.CharField(
max_length=150,
null=True,
blank=True,
help_text=help_text.Notice.TITLE,
)
body_markdown = models.CharField(
max_length=10000,
null=True,
blank=True,
help_text=help_text.Notice.BODY,
)
material_icon = models.CharField(
max_length=50, null=True, blank=True,
help_text=help_text.Notice.MATERIAL_ICON,
)
enabled = models.BooleanField(
default=False,
help_text="Display on the portal landing page."
)
is_published = models.BooleanField(
default=False,
help_text=(
"Unpublished content is visible to admin users only."
" Use this to review content before release to public users."
),
)

@property
def timestamp(self):
"""Return timestamp for notice."""
return self.datetime_modified.isoformat()

@property
def url(self):
"""Return the URL for this notice."""
return f"/notice/{self.id}"

def __str__(self):
"""Return string representation."""
return f"[{self.notice_class}] {self.title_html}"

def clean(self):
"""Clean fields before saving."""
super().clean()
if self.material_icon:
self.material_icon = self.material_icon.lower().replace(' ', '_')
26 changes: 26 additions & 0 deletions app/home/static/home/css/admin-mde.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/* Customise the admin markdown editor */

/* .editor-toolbar, */
.CodeMirror,
.editor-preview-side,
.editor-statusbar {
margin-left: 170px;
}
.CodeMirror {
margin-right: 300px;
}
.CodeMirror.CodeMirror-wrap {
width: calc(100% - 170px);
min-width: 400px;
}
.field-body img {
max-width: 100%;
}

/* Overwrite django admin styling */
.editor-preview ul {
margin-left: 1rem !important;
}
.editor-preview ul li {
list-style-type: disc !important;
}
3 changes: 3 additions & 0 deletions app/home/static/home/css/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ ol li ol li ol {
ol li {
padding: .5rem 0;
}
.material-icons {
vertical-align: bottom;
}
.li-h3 {
font-size: 1.7rem;
}
Expand Down
64 changes: 64 additions & 0 deletions app/home/static/home/css/notice.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/* Alert bar */
#notice-bar {
text-align: center;
width: calc(100% + 4rem);
margin: 0 -2rem 0 -2rem;
position: relative;
}
#notice-bar .notice-control {
color: var(--color);
background: transparent;
border: 1px solid transparent;
border-radius: 50%;
padding: 0;
margin: 0;
width: 2rem;
height: 2rem;
text-align: center;
position: absolute;
top: calc(8px - 0.1rem);
font-size: 2rem;
cursor: pointer;
transition-duration: .25s;
z-index: 100;
line-height: 0.82;
-webkit-user-select: none;
-ms-user-select: none;
user-select: none;
}
#notice-bar .notice-control:hover {
background-color: rgba(0,0,0,0.1);
}
#notice-left {
left: 2rem;
}
#notice-right {
right: 2rem;
}
#notice-bar .notice {
margin: 0 0 .1rem 0;
padding: .3rem .5rem .1rem .5rem;
width: 100%;
white-space: nowrap;
}
#notice-bar .notice.clickable {
cursor: pointer;
}
#notice-bar .notice.clickable:hover .body {
text-decoration: underline;
-webkit-transition: all .5s;
-moz-transition: all .5s;
-o-transition: all .5s;
transition: all .5s;
}
#notice-bar .notice .body {
display: inline-block;
overflow: hidden;
text-overflow: ellipsis;
padding: 0 5rem;
width: 100%;
}
.notice p {
margin-bottom: .5rem;
font-size: .9rem;
}
9 changes: 9 additions & 0 deletions app/home/static/home/js/admin-mde.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Add markdown editor to the "body" field in django admin

(function($) {
$(document).ready( () => {
new SimpleMDE({
element: document.getElementById("id_body_markdown")
});
});
})(django.jQuery);
Loading

0 comments on commit e71aa50

Please sign in to comment.