diff options
44 files changed, 1223 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6d9ca3f --- /dev/null +++ b/.gitignore @@ -0,0 +1,22 @@ +*.swp +*.pyc +*.mo +*~ +.~* +*.ignore +*.ignore.py +*.ignore.sql +local_settings.py +fabfile.py +Makefile +Dockerfile +db.sqlite3 +media/* +.cache +*.log +bootstrap-src +node_modules/ +package-lock.json +.idea +.code-workspace +.vscode/* diff --git a/Makefile.example b/Makefile.example new file mode 100644 index 0000000..2d14495 --- /dev/null +++ b/Makefile.example @@ -0,0 +1,47 @@ +SHELL := /bin/bash + +PYTHON=python3 + + +help: + # Actions available: + # * clean: remove temporary files + # * test: launch tests + # * soft_test: launch tests without db reinitialization + # * run: run local test server (port 9000) + # * shell: launch a python shell with project context preloaded + # * makemessages: create messages to be translated + # * compilemessages: compile messages to be translated + +clean: + -rm -rf *~* + -find . -name '*.pyc' -exec rm {} \; + -find . -name '.*.swp' -exec rm {} \; + -find . -name '__pycache__' -exec rm -rf {} \; 2> /dev/null + -rm -rf dist ishtar.egg-info + +test: clean + $(PYTHON) manage.py test + +soft_test: clean + $(PYTHON) manage.py test -k + +migrations: + $(PYTHON) manage.py makemigrations + +migrate: + $(PYTHON) manage.py migrate + +shell: + $(PYTHON) manage.py shell + +run: + $(PYTHON) manage.py runserver 0.0.0.0:9000 + +makemessages: + $(PYTHON) manage.py makemessages + +compilemessages: + $(PYTHON) manage.py compilemessages + + diff --git a/home/__init__.py b/home/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/home/__init__.py diff --git a/home/migrations/0001_initial.py b/home/migrations/0001_initial.py new file mode 100644 index 0000000..e718441 --- /dev/null +++ b/home/migrations/0001_initial.py @@ -0,0 +1,30 @@ +# Generated by Django 2.2.3 on 2019-07-16 09:07 + +from django.db import migrations, models +import django.db.models.deletion +import wagtail.core.fields + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('wagtailcore', '0041_group_collection_permissions_verbose_name_plural'), + ('wagtailimages', '0001_squashed_0021'), + ] + + operations = [ + migrations.CreateModel( + name='HomePage', + fields=[ + ('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.Page')), + ('body', wagtail.core.fields.RichTextField(blank=True)), + ('image', models.ForeignKey(blank=True, help_text='For top page: full width image. For child page: vignette.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailimages.Image')), + ], + options={ + 'abstract': False, + }, + bases=('wagtailcore.page',), + ), + ] diff --git a/home/migrations/__init__.py b/home/migrations/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/home/migrations/__init__.py diff --git a/home/models.py b/home/models.py new file mode 100644 index 0000000..64acee0 --- /dev/null +++ b/home/models.py @@ -0,0 +1,30 @@ +from django.db import models +from django.utils.translation import ugettext_lazy as _ + +from wagtail.core.models import Page +from wagtail.core.fields import RichTextField +from wagtail.admin.edit_handlers import FieldPanel +from wagtail.images.edit_handlers import ImageChooserPanel + + +class BasePage(Page): + image = models.ForeignKey( + 'wagtailimages.Image', on_delete=models.SET_NULL, related_name='+', + help_text=_( + "For top page: full width image. For child page: vignette." + ), blank=True, null=True + ) + body = RichTextField(blank=True) + + content_panels = Page.content_panels + [ + ImageChooserPanel('image'), + FieldPanel('body', classname="full"), + ] + + class Meta: + abstract = True + + +class HomePage(BasePage): + pass + diff --git a/home/static/css/welcome_page.css b/home/static/css/welcome_page.css new file mode 100644 index 0000000..ce8b149 --- /dev/null +++ b/home/static/css/welcome_page.css @@ -0,0 +1,204 @@ +html { + box-sizing: border-box; +} + +*, +*:before, +*:after { + box-sizing: inherit; +} + +body { + max-width: 960px; + min-height: 100vh; + margin: 0 auto; + padding: 0 15px; + color: #231f20; + font-family: 'Helvetica Neue', 'Segoe UI', Arial, sans-serif; + line-height: 1.25; +} + +a { + background-color: transparent; + color: #308282; + text-decoration: underline; +} + +a:hover { + color: #ea1b10; +} + +h1, +h2, +h3, +h4, +h5, +p, +ul { + padding: 0; + margin: 0; + font-weight: 400; +} + +main { + display: block; /* For IE11 support */ +} + +svg:not(:root) { + overflow: hidden; +} + +.header { + display: flex; + justify-content: space-between; + align-items: center; + padding-top: 20px; + padding-bottom: 10px; + border-bottom: 1px solid #e6e6e6; +} + +.logo { + width: 150px; + margin-right: 20px; +} + +.logo a { + display: block; +} + +.figure-logo { + max-width: 150px; + max-height: 55.1px; +} + +.release-notes { + font-size: 14px; +} + +.main { + padding: 40px 0; + margin: 0 auto; + text-align: center; +} + +.figure-space { + max-width: 265px; +} + +@-webkit-keyframes pos { + 0%, 100% { + -webkit-transform: rotate(-6deg); + transform: rotate(-6deg); + } + 50% { + -webkit-transform: rotate(6deg); + transform: rotate(6deg); + } +} + +@keyframes pos { + 0%, 100% { + -webkit-transform: rotate(-6deg); + transform: rotate(-6deg); + } + 50% { + -webkit-transform: rotate(6deg); + transform: rotate(6deg); + } +} + +.egg { + fill: #43b1b0; + -webkit-animation: pos 3s ease infinite; + animation: pos 3s ease infinite; + -webkit-transform: translateY(50px); + transform: translateY(50px); + -webkit-transform-origin: 50% 80%; + transform-origin: 50% 80%; +} + +.main-text { + max-width: 400px; + margin: 5px auto; +} + +.main-text h1 { + font-size: 22px; +} + +.main-text p { + margin: 15px auto 0; +} + +.footer { + display: flex; + flex-wrap: wrap; + justify-content: space-between; + border-top: 1px solid #e6e6e6; + padding: 10px; +} + +.option { + display: block; + padding: 10px 10px 10px 34px; + position: relative; + text-decoration: none; +} + +.option svg { + width: 24px; + height: 24px; + fill: gray; + border: 1px solid #d9d9d9; + padding: 5px; + border-radius: 100%; + top: 10px; + left: 0; + position: absolute; +} + +.option h4 { + font-size: 19px; + text-decoration: underline; +} + +.option p { + padding-top: 3px; + color: #231f20; + font-size: 15px; + font-weight: 300; +} + +@media (max-width: 996px) { + body { + max-width: 780px; + } +} + +@media (max-width: 767px) { + .option { + flex: 0 0 50%; + } +} + +@media (max-width: 599px) { + .main { + padding: 20px 0; + } + + .figure-space { + max-width: 200px; + } + + .footer { + display: block; + width: 300px; + margin: 0 auto; + } +} + +@media (max-width: 360px) { + .header-link { + max-width: 100px; + } +} diff --git a/home/templates/home/home_page.html b/home/templates/home/home_page.html new file mode 100644 index 0000000..d35a0f7 --- /dev/null +++ b/home/templates/home/home_page.html @@ -0,0 +1,37 @@ +{% extends "base.html" %} +{% load i18n static wagtailcore_tags %} + +{% block body_class %}template-homepage{% endblock %} + +{% block extra_css %} +<link rel="stylesheet" href="{% static 'css/welcome_page.css' %}"> +{% endblock extra_css %} + +{% block content %} +<header class="header"> + <div class="logo"> + </div> + <div class="header-link"> + </div> +</header> +<main> + {{ page.body|richtext }} + <ul> + {% for subpage in page.get_children %} + <li> + <a href="{% pageurl subpage %}">{{subpage.title}}</a> + {{ page.body|richtext }} + </li> + {% endfor %} + </ul> +</main> + +<footer class="footer"> + <a class="option option-three" href="{% url 'wagtailadmin_home' %}"> + <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true"><path d="M0 0h24v24H0z" fill="none"/><path d="M16.5 13c-1.2 0-3.07.34-4.5 1-1.43-.67-3.3-1-4.5-1C5.33 13 1 14.08 1 16.25V19h22v-2.75c0-2.17-4.33-3.25-6.5-3.25zm-4 4.5h-10v-1.25c0-.54 2.56-1.75 5-1.75s5 1.21 5 1.75v1.25zm9 0H14v-1.25c0-.46-.2-.86-.52-1.22.88-.3 1.96-.53 3.02-.53 2.44 0 5 1.21 5 1.75v1.25zM7.5 12c1.93 0 3.5-1.57 3.5-3.5S9.43 5 7.5 5 4 6.57 4 8.5 5.57 12 7.5 12zm0-5.5c1.1 0 2 .9 2 2s-.9 2-2 2-2-.9-2-2 .9-2 2-2zm9 5.5c1.93 0 3.5-1.57 3.5-3.5S18.43 5 16.5 5 13 6.57 13 8.5s1.57 3.5 3.5 3.5zm0-5.5c1.1 0 2 .9 2 2s-.9 2-2 2-2-.9-2-2 .9-2 2-2z"/></svg> + <div> + <h4>{% trans "Admin Interface" %}</h4> + </div> + </a> +</footer> +{% endblock %} diff --git a/home/templates/home/home_page.html.py b/home/templates/home/home_page.html.py new file mode 100644 index 0000000..a54a37e --- /dev/null +++ b/home/templates/home/home_page.html.py @@ -0,0 +1,37 @@ +BBBBBBB BBBBBBBBBBB +BBBB BBBB BBBBBB BBBBBBBBBBBBBBBB + +BBBBB BBBBBBBBBBXXXXXXXXXXXXXXXXXBBBBBBBB + +BBBBB BBBBBBBBB +XXXXX XXXXXXXXXXXXXXXX XXXXXXBBBBBB BBBBBBBBBBBBBBBBBBBBBBXX +BBBBBBBB BBBBBBBBB + +BBBBB BBBBBBB +XXXXXXX XXXXXXXXXXXXXXX + XXXX XXXXXXXXXXXXX + XXXXXX + XXXX XXXXXXXXXXXXXXXXXXXX + XXXXXX +XXXXXXXXX +XXXXXX + FFFFFFFF + XXXX + BBB BBBBBBB BB BBBBBBBBBBBBBBBBB + XXXX + XX XXXXXXBBBBBBB BBBBBBBXXXXXX + FFFFFFFF + XXXXX + BBBBBB + XXXXX +XXXXXXX + +XXXXXXX XXXXXXXXXXXXXXX + XX XXXXXXXXXXXXX XXXXXXXXXXXXX XXXXXXBBB BBBBBBBBBBBBBBBBBBBXX + XXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXX X XX XXX XXXXXXXXXXXXXXXXXXXXXXXX XXXXX XXXXXXXXXXX XXXXXXXXXXXXXXXXXX XXXXXXXX XXXXXXX XXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXX XX X XXXXX X XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXX XXXXXXXXX XXXXXXXX XXXX X XXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXX XXXXXXXX XXXX X X XXXX X XXXXXXXXXXXXXX XXXXXXX X XXXXXXXX XXXXXXXXXXXX X XXX X X XXXX X XXX XXXX XX XXX XXXXXXXXXXXXX X X XX X XXXXX XXX XXXXXXXXXX XXXX XXXXXX XXXXXXXX X XXXXXXXX XXXXXXXXXXXXX X XXXX X XX XXXX XX XXXXXXXX XXX XXX XXXXXXXXXXXXXX X X XX X XXXXX XXX XXXXXXXXXX XXXX XXXXXXXXXXXXX + XXXXX + XXXX gettext(u'Admin Interface') XXXXX + XXXXXX + XXXX +XXXXXXXXX +BBBBBBBB diff --git a/home/templates/home/welcome_page.html b/home/templates/home/welcome_page.html new file mode 100644 index 0000000..8918e3e --- /dev/null +++ b/home/templates/home/welcome_page.html @@ -0,0 +1,52 @@ +{% load i18n wagtailcore_tags %} + +<header class="header"> + <div class="logo"> + <a href="https://wagtail.io/"> + <svg class="figure-logo" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 342.5 126.2"><title>{% trans "Visit the Wagtail website" %}</title><path fill="#FFF" d="M84 1.9v5.7s-10.2-3.8-16.8 3.1c-4.8 5-5.2 10.6-3 18.1 21.6 0 25 12.1 25 12.1L87 27l6.8-8.3c0-9.8-8.1-16.3-9.8-16.8z"/><circle cx="85.9" cy="15.9" r="2.6"/><path d="M89.2 40.9s-3.3-16.6-24.9-12.1c-2.2-7.5-1.8-13 3-18.1C73.8 3.8 84 7.6 84 7.6V1.9C80.4.3 77 0 73.2 0 59.3 0 51.6 10.4 48.3 17.4L9.2 89.3l11-2.1-20.2 39 14.1-2.5L24.9 93c30.6 0 69.8-11 64.3-52.1z"/><path d="M102.4 27l-8.6-8.3L87 27z"/><path fill="#FFF" d="M30 84.1s1-.2 2.8-.6c1.8-.4 4.3-1 7.3-1.8 1.5-.4 3.1-.9 4.8-1.5 1.7-.6 3.5-1.2 5.2-2 1.8-.7 3.6-1.6 5.4-2.6 1.8-1 3.5-2.1 5.1-3.4.4-.3.8-.6 1.2-1l1.2-1c.7-.7 1.5-1.4 2.2-2.2.7-.7 1.3-1.5 1.9-2.3l.9-1.2.4-.6.4-.6c.2-.4.5-.8.7-1.2.2-.4.4-.8.7-1.2l.3-.6.3-.6c.2-.4.4-.8.5-1.2l.9-2.4c.2-.8.5-1.6.7-2.3.2-.7.3-1.5.5-2.1.1-.7.2-1.3.3-2 .1-.6.2-1.2.2-1.7.1-.5.1-1 .2-1.5.1-1.8.1-2.8.1-2.8l1.6.1s-.1 1.1-.2 2.9c-.1.5-.1 1-.2 1.5-.1.6-.1 1.2-.3 1.8-.1.6-.3 1.3-.4 2-.2.7-.4 1.4-.6 2.2-.2.8-.5 1.5-.8 2.4-.3.8-.6 1.6-1 2.5l-.6 1.2-.3.6-.3.6c-.2.4-.5.8-.7 1.3-.3.4-.5.8-.8 1.2-.1.2-.3.4-.4.6l-.4.6-.9 1.2c-.7.8-1.3 1.6-2.1 2.3-.7.8-1.5 1.4-2.3 2.2l-1.2 1c-.4.3-.8.6-1.3.9-1.7 1.2-3.5 2.3-5.3 3.3-1.8.9-3.7 1.8-5.5 2.5-1.8.7-3.6 1.3-5.3 1.8-1.7.5-3.3 1-4.9 1.3-3 .7-5.6 1.3-7.4 1.6-1.6.6-2.6.8-2.6.8z"/><g fill="#231F20"><path d="M127 83.9h-8.8l-12.6-36.4h7.9l9 27.5 9-27.5h7.9l9 27.5 9-27.5h7.9L153 83.9h-8.8L135.6 59 127 83.9zM200.1 83.9h-7V79c-3 3.6-7 5.4-12.1 5.4-3.8 0-6.9-1.1-9.4-3.2s-3.7-5-3.7-8.6c0-3.6 1.3-6.3 4-8 2.6-1.8 6.2-2.7 10.7-2.7h9.9v-1.4c0-4.8-2.7-7.3-8.1-7.3-3.4 0-6.9 1.2-10.5 3.7l-3.4-4.8c4.4-3.5 9.4-5.3 15.1-5.3 4.3 0 7.8 1.1 10.5 3.2 2.7 2.2 4.1 5.6 4.1 10.2v23.7zm-7.7-13.6v-3.1h-8.6c-5.5 0-8.3 1.7-8.3 5.2 0 1.8.7 3.1 2.1 4.1 1.4.9 3.3 1.4 5.7 1.4 2.4 0 4.6-.7 6.4-2.1 1.8-1.3 2.7-3.1 2.7-5.5zM241.7 47.5v31.7c0 6.4-1.7 11.3-5.2 14.5-3.5 3.2-8 4.8-13.4 4.8-5.5 0-10.4-1.7-14.8-5.1l3.6-5.8c3.6 2.7 7.1 4 10.8 4 3.6 0 6.5-.9 8.6-2.8 2.1-1.9 3.2-4.9 3.2-9v-4.7c-1.1 2.1-2.8 3.9-4.9 5.1-2.1 1.3-4.5 1.9-7.1 1.9-4.8 0-8.8-1.7-11.9-5.1-3.1-3.4-4.7-7.6-4.7-12.6s1.6-9.2 4.7-12.6c3.1-3.4 7.1-5.1 11.9-5.1 4.8 0 8.7 2 11.7 6v-5.4h7.5zm-28.4 16.8c0 3 .9 5.6 2.8 7.7 1.8 2.2 4.3 3.2 7.5 3.2 3.1 0 5.7-1 7.6-3.1 1.9-2.1 2.9-4.7 2.9-7.8 0-3.1-1-5.8-2.9-7.9-2-2.2-4.5-3.2-7.6-3.2-3.1 0-5.6 1.1-7.4 3.4-2 2.1-2.9 4.7-2.9 7.7zM260.9 53.6v18.5c0 1.7.5 3.1 1.4 4.1.9 1 2.2 1.5 3.8 1.5 1.6 0 3.2-.8 4.7-2.4l3.1 5.4c-2.7 2.4-5.7 3.6-8.9 3.6-3.3 0-6-1.1-8.3-3.4-2.3-2.3-3.5-5.3-3.5-9.1V53.6h-4.6v-6.2h4.6V36.1h7.7v11.4h9.6v6.2h-9.6zM309.5 83.9h-7V79c-3 3.6-7 5.4-12.1 5.4-3.8 0-6.9-1.1-9.4-3.2s-3.7-5-3.7-8.6c0-3.6 1.3-6.3 4-8 2.6-1.8 6.2-2.7 10.7-2.7h9.9v-1.4c0-4.8-2.7-7.3-8.1-7.3-3.4 0-6.9 1.2-10.5 3.7l-3.4-4.8c4.4-3.5 9.4-5.3 15.1-5.3 4.3 0 7.8 1.1 10.5 3.2 2.7 2.2 4.1 5.6 4.1 10.2v23.7zm-7.7-13.6v-3.1h-8.6c-5.5 0-8.3 1.7-8.3 5.2 0 1.8.7 3.1 2.1 4.1 1.4.9 3.3 1.4 5.7 1.4 2.4 0 4.6-.7 6.4-2.1 1.8-1.3 2.7-3.1 2.7-5.5zM319.3 40.2c-1-1-1.4-2.1-1.4-3.4 0-1.3.5-2.5 1.4-3.4 1-1 2.1-1.4 3.4-1.4 1.3 0 2.5.5 3.4 1.4 1 1 1.4 2.1 1.4 3.4 0 1.3-.5 2.5-1.4 3.4s-2.1 1.4-3.4 1.4c-1.3.1-2.4-.4-3.4-1.4zm7.2 43.7h-7.7V47.5h7.7v36.4zM342.5 83.9h-7.7V33.1h7.7v50.8z"/></g></svg> + </a> + </div> + <div class="header-link"> + {% comment %} + This works for all cases but prerelease versions: + {% endcomment %} + <a href="{% wagtail_documentation_path %}/releases/{% wagtail_release_notes_path %}"> + {% trans "View the release notes" %} + </a> + </div> +</header> +<main class="main"> + <div class="figure"> + <svg class="figure-space" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300" aria-hidden="true"> + <path class="egg" fill="currentColor" d="M150 250c-42.741 0-75-32.693-75-90s42.913-110 75-110c32.088 0 75 52.693 75 110s-32.258 90-75 90z"/> + <ellipse fill="#ddd" cx="150" cy="270" rx="40" ry="7"/> + </svg> + </div> + <div class="main-text"> + <h1>{% trans "Welcome to your new Wagtail site!" %}</h1> + <p>{% trans 'Please feel free to <a href="https://github.com/wagtail/wagtail/wiki/Slack">join our community on Slack</a>, or get started with one of the links below.' %}</p> + </div> +</main> +<footer class="footer"> + <a class="option option-one" href="{% wagtail_documentation_path %}/"> + <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true"><path d="M9 21c0 .5.4 1 1 1h4c.6 0 1-.5 1-1v-1H9v1zm3-19C8.1 2 5 5.1 5 9c0 2.4 1.2 4.5 3 5.7V17c0 .5.4 1 1 1h6c.6 0 1-.5 1-1v-2.3c1.8-1.3 3-3.4 3-5.7 0-3.9-3.1-7-7-7zm2.9 11.1l-.9.6V16h-4v-2.3l-.9-.6C7.8 12.2 7 10.6 7 9c0-2.8 2.2-5 5-5s5 2.2 5 5c0 1.6-.8 3.2-2.1 4.1z"/></svg> + <div> + <h4>{% trans "Wagtail Documentation" %}</h4> + <p>{% trans "Topics, references, & how-tos" %}</p> + </div> + </a> + <a class="option option-two" href="{% wagtail_documentation_path %}/getting_started/tutorial.html"> + <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M9.4 16.6L4.8 12l4.6-4.6L8 6l-6 6 6 6 1.4-1.4zm5.2 0l4.6-4.6-4.6-4.6L16 6l6 6-6 6-1.4-1.4z"/></svg> + <div> + <h4>{% trans "Tutorial" %}</h4> + <p>{% trans "Build your first Wagtail site" %}</p> + </div> + </a> + <a class="option option-three" href="{% url 'wagtailadmin_home' %}"> + <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true"><path d="M0 0h24v24H0z" fill="none"/><path d="M16.5 13c-1.2 0-3.07.34-4.5 1-1.43-.67-3.3-1-4.5-1C5.33 13 1 14.08 1 16.25V19h22v-2.75c0-2.17-4.33-3.25-6.5-3.25zm-4 4.5h-10v-1.25c0-.54 2.56-1.75 5-1.75s5 1.21 5 1.75v1.25zm9 0H14v-1.25c0-.46-.2-.86-.52-1.22.88-.3 1.96-.53 3.02-.53 2.44 0 5 1.21 5 1.75v1.25zM7.5 12c1.93 0 3.5-1.57 3.5-3.5S9.43 5 7.5 5 4 6.57 4 8.5 5.57 12 7.5 12zm0-5.5c1.1 0 2 .9 2 2s-.9 2-2 2-2-.9-2-2 .9-2 2-2zm9 5.5c1.93 0 3.5-1.57 3.5-3.5S18.43 5 16.5 5 13 6.57 13 8.5s1.57 3.5 3.5 3.5zm0-5.5c1.1 0 2 .9 2 2s-.9 2-2 2-2-.9-2-2 .9-2 2-2z"/></svg> + <div> + <h4>{% trans "Admin Interface" %}</h4> + <p>{% trans "Create your superuser first!" %}</p> + </div> + </a> +</footer> diff --git a/home/templates/home/welcome_page.html.py b/home/templates/home/welcome_page.html.py new file mode 100644 index 0000000..d1123ac --- /dev/null +++ b/home/templates/home/welcome_page.html.py @@ -0,0 +1,53 @@ +BBBB BBBB BBBBBBBBBBBBBBBB + +XXXXXXX XXXXXXXXXXXXXXX + XXXX XXXXXXXXXXXXX + XX XXXXXXXXXXXXXXXXXXXXXXXXXXX + XXXX XXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXX X XXXXX XXXXXXXXXXXXXX gettext(u'Visit the Wagtail website') XXXXXXXXXXXXX XXXXXXXXXXX XXXXXX XXXXXXXXXXXXXXXXXXXXXX XXXXXXXX XXXXX XXXXXX XXXX XXXX X XX XXXX XX XXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXX XXXXXXXXX XXXXXXXXXXXXXX XXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXX XXX XX XXX XX XXXXXXXXXXXXXX XX X XXXX X XXXX X XXXX XXXX XXXX XXXXXXXX XXXXXXXXXXXXXXXX XX XXXXXXXXXXXXX XXXXXXX X XXXXXXX XXXXXXXXXXXXXXXXXX XXXXXXXXX XXXXXXXXXXXXXX XXXXXXXXXXX XXXXXXXXXXX XXXXXX XXXXXXXXX XXXXXXXXXXXXX XXXXX XXXXXXX XXXXXX XXXXXX XXXXXXX XXXXXX XXXXXXX XXXXX XXXXXX XXXXXXX XXXXXXX XXXXX XXXXXXX XXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXX XXXXXXX XXXXXXXXXXXX XXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXX XXXXXXXXXXXX XXXX XXXXXXXXXXX XXXXXX XXXXXXXXXXX XXXXXX XXXXXXXXX XXXXXX XXXXXXXXXXX XXXXXX XXXXXXXXXXX XXXXX XXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXX XXXXXXX XXXXXXXXXXXX XXXXXXX XXXXXXXX XXXXXXXXXXXXXXXXXXXXXX XXXXXXX XXXXXXX XXXXXXXXXXXXX XXXXXXX XXXXXXXXXXXXX XXXXXXX XXXXXXXXXXXXX XXXXX XXXXX XXXXXX XXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXX XXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXX XXXX XXXXXXXXXXXX XXXX XXXXXXXXXXXXXX XXXXXXXXXXXXXXX XX XXX XXXXXXXXXXX XXXXXXXXXXXXX XXXXX XXXXXXXX XXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXX XXX XXXXXXX XXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXX XXXXXXXX XXXXXXXXXXXXXXXXXXXX XXXXXXX XXXXXXXX XXX X XXX XXX XXXX XXX XXX XXX XXX XXX XXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXX XXXXXXX XXX X XXXXX XXX XXX XXX XXXXX XXX XXX XXX XXX XXX X XXXXXX XXXXXXX XXXXXXX XXXXXXX XXXXXXXXXXXXXX XXXXXXXXXXX XXXXXXX XXXXXXXX XXXXXXXX XXXXX XXXXXXXX XXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXX XXX X XXXX X XXX X XXXXXX XXXXXXX XXXXXXX XXXXXXX XXXXXXXXXXXXXXX XXXXXXX XXXXXXX XXXXXXX XXXXXXX XXXXXXX XXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXX XXXXXXXX XXX X XXX X XXXX XXXXXXXXXXXXXXXXX XXXXXX X XX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX X XXXXX XXXXXXX XXXXXXX XXXXXXX XXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXX XXXXXXX XXXXX XXXXXXX XXXXXXX XXXXXXXXXX XXXXXXXXXXX XXXXX XXX XXX XXXXX X XXX XXX XXX XXX XXX X XXXXXX XXXXXXXXXXX XXXXXXXX XXXXXXX XXXXXXX XXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXX XXXXX XXXXXXXX XXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXX XXX XXXXXXX XXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXX XXXXXXXX XXXXXXXXXXXXXXXXXXXX XXXXXXX XXXXXXXX XXX X XXX XXX XXXX XXX XXX XXX XXX XXX XXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXX XXXXXXX XXX X XXXXX XXX XXX XXX XXXXX XXX XXX XXX XXX XXX X XXXXXX XXXXXXX XXXXXXX XXXXXXX XXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXX XXXXXXX XXX XXXXXXX XXXXXXX XXX X XXXXX XXX XXX X X XXX XXX XXX XXX X XXXXXX XXXXXXX XXXXXXXX XXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + XXXX + XXXXXX + XXXX XXXXXXXXXXXXXXXXXXXX + # + # + # + + XX XXXXXXBBBBBBBBBBBBBBBBBBBBBBBBBBXXXXXXXXXXBBBBBBBBBBBBBBBBBBBBBBBBBBXX + gettext(u'View the release notes') + XXXX + XXXXXX +XXXXXXXXX +XXXXX XXXXXXXXXXXXX + XXXX XXXXXXXXXXXXXXX + XXXX XXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXX X XXX XXXX XXXXXXXXXXXXXXXXXXX + XXXXX XXXXXXXXXXX XXXXXXXXXXXXXXXXXXX XXXXXXX XXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXX X XX XXXXXX XX XXXXXXXXXXX XXXXX XXXXXX + XXXXXXXX XXXXXXXXXXX XXXXXXXX XXXXXXXX XXXXXXX XXXXXXXX + XXXXXX + XXXXXX + XXXX XXXXXXXXXXXXXXXXXX + XXXX gettext(u'Welcome to your new Wagtail site!') XXXXX + XXX gettext(u'Please feel free to <a href="https://github.com/wagtail/wagtail/wiki/Slack">join our community on Slack</a>, or get started with one of the links below.') XXXX + XXXXXX +XXXXXXX +XXXXXXX XXXXXXXXXXXXXXX + XX XXXXXXXXXXXXX XXXXXXXXXXX XXXXXXBBBBBBBBBBBBBBBBBBBBBBBBBBXXX + XXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXX X XX XXX XXXXXXXXXXXXXXXXXXXXXXXX XXXXX XXXX XXXX X X XXXXXX X XXXX XXXXXXXXXXXXXXXXXXXX X X XXX X XXX XXX XXX XXX X XXXXXXXX XXXX X X XXXXXX X XXXX XXXXXXXXXXXXXXXX XXXXX XXXXX XXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXX X XXXX X XXXXXXX XXXXX XXXXX XXX X XXX XXXXXX XXXXXXX XXXXXXXXXXXXX + XXXXX + XXXX gettext(u'Wagtail Documentation') XXXXX + XXX gettext(u'Topics, references, & how-tos') XXXX + XXXXXX + XXXX + XX XXXXXXXXXXXXX XXXXXXXXXXX XXXXXXBBBBBBBBBBBBBBBBBBBBBBBBBBXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + XXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXX X XX XXX XXXXXXXXXXXXXXXXXXXXXXXX XXXXX XXXXXXXXXXXXX XXXXXXXXXXXXXXXXXX XXXXXXX XXXXXXXX XXXXXXXXXXXX XXXX X X X XXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXX XXX XXX XXXXXXXXXXXXXXXXXXX + XXXXX + XXXX gettext(u'Tutorial') XXXXX + XXX gettext(u'Build your first Wagtail site') XXXX + XXXXXX + XXXX + XX XXXXXXXXXXXXX XXXXXXXXXXXXX XXXXXXBBB BBBBBBBBBBBBBBBBBBBXX + XXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXX X XX XXX XXXXXXXXXXXXXXXXXXXXXXXX XXXXX XXXXXXXXXXX XXXXXXXXXXXXXXXXXX XXXXXXXX XXXXXXX XXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXX XX X XXXXX X XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXX XXXXXXXXX XXXXXXXX XXXX X XXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXX XXXXXXXX XXXX X X XXXX X XXXXXXXXXXXXXX XXXXXXX X XXXXXXXX XXXXXXXXXXXX X XXX X X XXXX X XXX XXXX XX XXX XXXXXXXXXXXXX X X XX X XXXXX XXX XXXXXXXXXX XXXX XXXXXX XXXXXXXX X XXXXXXXX XXXXXXXXXXXXX X XXXX X XX XXXX XX XXXXXXXX XXX XXX XXXXXXXXXXXXXX X X XX X XXXXX XXX XXXXXXXXXX XXXX XXXXXXXXXXXXX + XXXXX + XXXX gettext(u'Admin Interface') XXXXX + XXX gettext(u'Create your superuser first!') XXXX + XXXXXX + XXXX +XXXXXXXXX diff --git a/home/views.py b/home/views.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/home/views.py diff --git a/ishtar_public/__init__.py b/ishtar_public/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/ishtar_public/__init__.py diff --git a/ishtar_public/settings/__init__.py b/ishtar_public/settings/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/ishtar_public/settings/__init__.py diff --git a/ishtar_public/settings/base.py b/ishtar_public/settings/base.py new file mode 100644 index 0000000..dff1911 --- /dev/null +++ b/ishtar_public/settings/base.py @@ -0,0 +1,176 @@ +""" +Django settings for ishtar_public project. + +Generated by 'django-admin startproject' using Django 2.2.3. + +For more information on this file, see +https://docs.djangoproject.com/en/2.2/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/2.2/ref/settings/ +""" + +# Build paths inside the project like this: os.path.join(BASE_DIR, ...) +import os + +PROJECT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +BASE_DIR = os.path.dirname(PROJECT_DIR) + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/ + + +# Application definition + +INSTALLED_APPS = [ + 'home', + 'showcase', + 'search', + + 'wagtail.contrib.forms', + 'wagtail.contrib.redirects', + 'wagtail.embeds', + 'wagtail.sites', + 'wagtail.users', + 'wagtail.snippets', + 'wagtail.documents', + 'wagtail.images', + 'wagtail.search', + 'wagtail.admin', + 'wagtail.core', + 'wagtail.contrib.modeladmin', + + 'modelcluster', + 'taggit', + + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', +] + +MIDDLEWARE = [ + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', + 'django.middleware.security.SecurityMiddleware', + + 'wagtail.core.middleware.SiteMiddleware', + 'wagtail.contrib.redirects.middleware.RedirectMiddleware', +] + +ROOT_URLCONF = 'ishtar_public.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [ + os.path.join(PROJECT_DIR, 'templates'), + ], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'ishtar_public.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/2.2/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } +} + + +# Password validation +# https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/2.2/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_L10N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/2.2/howto/static-files/ + +STATICFILES_FINDERS = [ + 'django.contrib.staticfiles.finders.FileSystemFinder', + 'django.contrib.staticfiles.finders.AppDirectoriesFinder', +] + +STATICFILES_DIRS = [ + os.path.join(PROJECT_DIR, 'static'), +] + +# ManifestStaticFilesStorage is recommended in production, to prevent outdated +# Javascript / CSS assets being served from cache (e.g. after a Wagtail upgrade). +# See https://docs.djangoproject.com/en/2.2/ref/contrib/staticfiles/#manifeststaticfilesstorage +STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.ManifestStaticFilesStorage' + +STATIC_ROOT = os.path.join(BASE_DIR, 'static') +STATIC_URL = '/static/' + +MEDIA_ROOT = os.path.join(BASE_DIR, 'media') +MEDIA_URL = '/media/' + +CACHES = { + 'default': { + 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', + 'LOCATION': '127.0.0.1:11211', + 'TIMEOUT': 3600, + } +} + + +# Wagtail settings + +WAGTAIL_SITE_NAME = "ishtar_public" + +# extra slug when multiple ishtar site are running on the same host +WAGTAIL_EXTRA_SLUG = "" + +# Base URL to use when referring to full URLs within the Wagtail admin backend - +# e.g. in notification emails. Don't include '/admin' or a trailing slash +BASE_URL = 'http://example.com' diff --git a/ishtar_public/settings/dev.py b/ishtar_public/settings/dev.py new file mode 100644 index 0000000..b7705b8 --- /dev/null +++ b/ishtar_public/settings/dev.py @@ -0,0 +1,18 @@ +from .base import * + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = '*woiq$=w@joi+vb7-d951_xd9$-85et(0fmlh&^rnz_u#@(p61' + +# SECURITY WARNING: define the correct hosts in production! +ALLOWED_HOSTS = ['*'] + +EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' + + +try: + from .local import * +except ImportError: + pass diff --git a/ishtar_public/settings/production.py b/ishtar_public/settings/production.py new file mode 100644 index 0000000..9ca4ed7 --- /dev/null +++ b/ishtar_public/settings/production.py @@ -0,0 +1,8 @@ +from .base import * + +DEBUG = False + +try: + from .local import * +except ImportError: + pass diff --git a/ishtar_public/static/css/ishtar_public.css b/ishtar_public/static/css/ishtar_public.css new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/ishtar_public/static/css/ishtar_public.css diff --git a/ishtar_public/static/js/ishtar_public.js b/ishtar_public/static/js/ishtar_public.js new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/ishtar_public/static/js/ishtar_public.js diff --git a/ishtar_public/templates/404.html b/ishtar_public/templates/404.html new file mode 100644 index 0000000..3a5500e --- /dev/null +++ b/ishtar_public/templates/404.html @@ -0,0 +1,9 @@ +{% extends "base.html" %} + +{% block body_class %}template-404{% endblock %} + +{% block content %} + <h1>Page not found</h1> + + <h2>Sorry, this page could not be found.</h2> +{% endblock %} diff --git a/ishtar_public/templates/404.html.py b/ishtar_public/templates/404.html.py new file mode 100644 index 0000000..629a68b --- /dev/null +++ b/ishtar_public/templates/404.html.py @@ -0,0 +1,9 @@ +BBBBBBB BBBBBBBBBBB + +BBBBB BBBBBBBBBBXXXXXXXXXXXXBBBBBBBB + +BBBBB BBBBBBB + XXXXXXXX XXX XXXXXXXXXX + + XXXXXXXXXX XXXX XXXX XXXXX XXX XX XXXXXXXXXXX +BBBBBBBB diff --git a/ishtar_public/templates/500.html b/ishtar_public/templates/500.html new file mode 100644 index 0000000..72b6406 --- /dev/null +++ b/ishtar_public/templates/500.html @@ -0,0 +1,13 @@ +<!DOCTYPE html> +<html class="no-js"> + <head> + <meta charset="utf-8" /> + <title>Internal server error</title> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + </head> + <body> + <h1>Internal server error</h1> + + <h2>Sorry, there seems to be an error. Please try again soon.</h2> + </body> +</html> diff --git a/ishtar_public/templates/500.html.py b/ishtar_public/templates/500.html.py new file mode 100644 index 0000000..e5865c6 --- /dev/null +++ b/ishtar_public/templates/500.html.py @@ -0,0 +1,13 @@ +XXXXXXXXX XXXXX +XXXXX XXXXXXXXXXXXXX + XXXXXX + XXXXX XXXXXXXXXXXXXXX XX + XXXXXXXXXXXXXXX XXXXXX XXXXXXXXXXXXX + XXXXX XXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XX + XXXXXXX + XXXXXX + XXXXXXXXXXXX XXXXXX XXXXXXXXXX + + XXXXXXXXXX XXXXX XXXXX XX XX XX XXXXXX XXXXXX XXX XXXXX XXXXXXXXXX + XXXXXXX +XXXXXXX diff --git a/ishtar_public/templates/base.html b/ishtar_public/templates/base.html new file mode 100644 index 0000000..169ac72 --- /dev/null +++ b/ishtar_public/templates/base.html @@ -0,0 +1,40 @@ +{% load static wagtailuserbar %} + +<!DOCTYPE html> +<html class="no-js" lang="en"> + <head> + <meta charset="utf-8" /> + <title> + {% block title %} + {% if self.seo_title %}{{ self.seo_title }}{% else %}{{ self.title }}{% endif %} + {% endblock %} + {% block title_suffix %} + {% with self.get_site.site_name as site_name %} + {% if site_name %}- {{ site_name }}{% endif %} + {% endwith %} + {% endblock %} + </title> + <meta name="description" content="" /> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + + {# Global stylesheets #} + <link rel="stylesheet" type="text/css" href="{% static 'css/ishtar_public.css' %}"> + + {% block extra_css %} + {# Override this in templates to add extra stylesheets #} + {% endblock %} + </head> + + <body class="{% block body_class %}{% endblock %}"> + {% wagtailuserbar %} + + {% block content %}{% endblock %} + + {# Global javascript #} + <script type="text/javascript" src="{% static 'js/ishtar_public.js' %}"></script> + + {% block extra_js %} + {# Override this in templates to add extra javascript #} + {% endblock %} + </body> +</html> diff --git a/ishtar_public/urls.py b/ishtar_public/urls.py new file mode 100644 index 0000000..c013e50 --- /dev/null +++ b/ishtar_public/urls.py @@ -0,0 +1,40 @@ +from django.conf import settings +from django.conf.urls import include, url +from django.contrib import admin + +from wagtail.admin import urls as wagtailadmin_urls +from wagtail.core import urls as wagtail_urls +from wagtail.documents import urls as wagtaildocs_urls + +from search import views as search_views +from showcase import urls as showcase_urls + + +urlpatterns = [ + url(r'^django-admin/', admin.site.urls), + + url(r'^admin/', include(wagtailadmin_urls)), + url(r'^documents/', include(wagtaildocs_urls)), + + url(r'^search/$', search_views.search, name='search'), + + url(r"^showcase/", include(showcase_urls)), + + # For anything not caught by a more specific rule above, hand over to + # Wagtail's page serving mechanism. This should be the last pattern in + # the list: + url(r'', include(wagtail_urls)), + + # Alternatively, if you want Wagtail pages to be served from a subpath + # of your site, rather than the site root: + # url(r'^pages/', include(wagtail_urls)), +] + + +if settings.DEBUG: + from django.conf.urls.static import static + from django.contrib.staticfiles.urls import staticfiles_urlpatterns + + # Serve static and media files from development server + urlpatterns += staticfiles_urlpatterns() + urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/ishtar_public/wsgi.py b/ishtar_public/wsgi.py new file mode 100644 index 0000000..8b67569 --- /dev/null +++ b/ishtar_public/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for ishtar_public project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/2.2/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "ishtar_public.settings.dev") + +application = get_wsgi_application() diff --git a/manage.py b/manage.py new file mode 100755 index 0000000..91cbd4d --- /dev/null +++ b/manage.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python +import os +import sys + +if __name__ == "__main__": + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "ishtar_public.settings.dev") + + from django.core.management import execute_from_command_line + + execute_from_command_line(sys.argv) diff --git a/media/.media-file-here b/media/.media-file-here new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/media/.media-file-here diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..3d4822b --- /dev/null +++ b/requirements.txt @@ -0,0 +1,5 @@ +Django>=2.2,<2.3 +wagtail>=2.5,<2.6 + +requests==2.12 +python-memcached==1.59 diff --git a/search/__init__.py b/search/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/search/__init__.py diff --git a/search/templates/search/search.html b/search/templates/search/search.html new file mode 100644 index 0000000..5f222e5 --- /dev/null +++ b/search/templates/search/search.html @@ -0,0 +1,38 @@ +{% extends "base.html" %} +{% load static wagtailcore_tags %} + +{% block body_class %}template-searchresults{% endblock %} + +{% block title %}Search{% endblock %} + +{% block content %} + <h1>Search</h1> + + <form action="{% url 'search' %}" method="get"> + <input type="text" name="query"{% if search_query %} value="{{ search_query }}"{% endif %}> + <input type="submit" value="Search" class="button"> + </form> + + {% if search_results %} + <ul> + {% for result in search_results %} + <li> + <h4><a href="{% pageurl result %}">{{ result }}</a></h4> + {% if result.search_description %} + {{ result.search_description }} + {% endif %} + </li> + {% endfor %} + </ul> + + {% if search_results.has_previous %} + <a href="{% url 'search' %}?query={{ search_query|urlencode }}&page={{ search_results.previous_page_number }}">Previous</a> + {% endif %} + + {% if search_results.has_next %} + <a href="{% url 'search' %}?query={{ search_query|urlencode }}&page={{ search_results.next_page_number }}">Next</a> + {% endif %} + {% elif search_query %} + No results found + {% endif %} +{% endblock %} diff --git a/search/views.py b/search/views.py new file mode 100644 index 0000000..eeace7c --- /dev/null +++ b/search/views.py @@ -0,0 +1,34 @@ +from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator +from django.shortcuts import render + +from wagtail.core.models import Page +from wagtail.search.models import Query + + +def search(request): + search_query = request.GET.get('query', None) + page = request.GET.get('page', 1) + + # Search + if search_query: + search_results = Page.objects.live().search(search_query) + query = Query.get(search_query) + + # Record hit + query.add_hit() + else: + search_results = Page.objects.none() + + # Pagination + paginator = Paginator(search_results, 10) + try: + search_results = paginator.page(page) + except PageNotAnInteger: + search_results = paginator.page(1) + except EmptyPage: + search_results = paginator.page(paginator.num_pages) + + return render(request, 'search/search.html', { + 'search_query': search_query, + 'search_results': search_results, + }) diff --git a/showcase/__init__.py b/showcase/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/showcase/__init__.py diff --git a/showcase/admin.py b/showcase/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/showcase/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/showcase/apps.py b/showcase/apps.py new file mode 100644 index 0000000..d879f9b --- /dev/null +++ b/showcase/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class ShowcaseConfig(AppConfig): + name = 'showcase' diff --git a/showcase/migrations/0001_initial.py b/showcase/migrations/0001_initial.py new file mode 100644 index 0000000..0abb7d7 --- /dev/null +++ b/showcase/migrations/0001_initial.py @@ -0,0 +1,63 @@ +# Generated by Django 2.2.3 on 2019-07-16 17:41 + +from django.db import migrations, models +import django.db.models.deletion +import wagtail.core.fields + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('wagtailcore', '0041_group_collection_permissions_verbose_name_plural'), + ('wagtailimages', '0001_squashed_0021'), + ] + + operations = [ + migrations.CreateModel( + name='ExternalSource', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=200)), + ('error', models.TextField(blank=True, null=True)), + ('api_url', models.URLField()), + ('api_key', models.CharField(blank=True, max_length=500, null=True)), + ], + options={ + 'verbose_name': 'External source', + 'verbose_name_plural': 'External sources', + }, + ), + migrations.CreateModel( + name='ExternalSourceType', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=200)), + ('slug', models.SlugField(max_length=200)), + ], + options={ + 'verbose_name': 'External source type', + 'verbose_name_plural': 'External source types', + }, + ), + migrations.CreateModel( + name='ShowCase', + fields=[ + ('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.Page')), + ('body', wagtail.core.fields.RichTextField(blank=True)), + ('external_source', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='showcase.ExternalSource')), + ('image', models.ForeignKey(blank=True, help_text='For top page: full width image. For child page: vignette.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailimages.Image')), + ], + options={ + 'verbose_name': 'Show case', + 'verbose_name_plural': 'Show cases', + }, + bases=('wagtailcore.page',), + ), + migrations.AddField( + model_name='externalsource', + name='source_type', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='showcase.ExternalSourceType'), + ), + ] diff --git a/showcase/migrations/__init__.py b/showcase/migrations/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/showcase/migrations/__init__.py diff --git a/showcase/models.py b/showcase/models.py new file mode 100644 index 0000000..ab04f93 --- /dev/null +++ b/showcase/models.py @@ -0,0 +1,103 @@ +import json +import requests + +from django.conf import settings +from django.core.cache import cache +from django.db import models +from django.utils.translation import ugettext_lazy as _ + +from wagtail.admin.edit_handlers import FieldPanel + +from home.models import BasePage + + +class ExternalSourceType(models.Model): + name = models.CharField(max_length=200) + slug = models.SlugField(max_length=200) + panels = [ + FieldPanel('name'), + FieldPanel('slug'), + ] + + class Meta: + verbose_name = _("External source type") + verbose_name_plural = _("External source types") + + def __str__(self): + return self.name + + +class ExternalSource(models.Model): + name = models.CharField(max_length=200) + error = models.TextField(null=True, blank=True) + source_type = models.ForeignKey(ExternalSourceType, + on_delete=models.PROTECT) + api_url = models.URLField() + api_key = models.CharField(max_length=500, null=True, blank=True) + panels = [ + FieldPanel('name'), + FieldPanel('source_type'), + FieldPanel('api_url'), + FieldPanel('api_key'), + ] + + class Meta: + verbose_name = _("External source") + verbose_name_plural = _("External sources") + + def __str__(self): + return self.name + + def get_data(self): + key = "{}{}-data-{}".format( + settings.WAGTAIL_SITE_NAME, settings.WAGTAIL_EXTRA_SLUG, + self.pk + ) + data = cache.get(key) + if data: + return data + data = [] + headers = {} + base_error = str(_("Error while fetching the source:")) + " " + if self.api_key: + headers = {'Authorization': 'token {}'.format(self.api_key)} + try: + response = requests.get(self.api_url, headers=headers) + data = json.loads(response.text) + cache.set(key, data) + self.error = "" + except requests.exceptions.Timeout: + self.error = base_error + str(_("connection time out")) + except requests.exceptions.TooManyRedirects: + self.error = base_error + str(_("too many redirection")) + except requests.exceptions.RequestException as e: + self.error = base_error + str(_("unknown error")) + " - " + str(e) + self.save() + return data + + @property + def data(self): + # TODO: cache + return self.get_data() + + def get_item(self, item_number): + if item_number >= len(self.data): + return + return self.data[item_number] + + +class ShowCase(BasePage): + external_source = models.ForeignKey(ExternalSource, + on_delete=models.PROTECT) + content_panels = [ + FieldPanel('slug'), FieldPanel('external_source') + ] + BasePage.content_panels + + class Meta: + verbose_name = _("Show case") + verbose_name_plural = _("Show cases") + + @property + def data(self): + return self.external_source.get_data() + diff --git a/showcase/templates/showcase/item-find.html b/showcase/templates/showcase/item-find.html new file mode 100644 index 0000000..3cd3b6f --- /dev/null +++ b/showcase/templates/showcase/item-find.html @@ -0,0 +1,12 @@ +{% extends "base.html" %} +{% load i18n static wagtailcore_tags wagtailimages_tags %} + +{% block body_class %}template-showcase{% endblock %} + +{% block content %} +<main> + {{denomination}} + <img src="{{images.0.thumbnail}}"> +</main> + +{% endblock %} diff --git a/showcase/templates/showcase/show_case.html b/showcase/templates/showcase/show_case.html new file mode 100644 index 0000000..4940b43 --- /dev/null +++ b/showcase/templates/showcase/show_case.html @@ -0,0 +1,22 @@ +{% extends "base.html" %} +{% load i18n static wagtailcore_tags wagtailimages_tags %} + +{% block body_class %}template-showcase{% endblock %} + +{% block content %} +<main> + {% image page.image width-500 %} + {{ page.body|richtext }} + {% if page.data %}<ul> + {% for item in page.data %} + <li> + <a href="{% url 'display-item' page.slug forloop.counter0 %}"> + {{item.denomination}} + <img src="{{item.images.0.thumbnail}}"> + </a> + </li> + {% endfor %} + </ul>{% endif %} +</main> + +{% endblock %} diff --git a/showcase/tests.py b/showcase/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/showcase/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/showcase/urls.py b/showcase/urls.py new file mode 100644 index 0000000..173d415 --- /dev/null +++ b/showcase/urls.py @@ -0,0 +1,8 @@ +from django.conf.urls import url + +from .views import display_item + +urlpatterns = [ + url(r'^display-item/(?P<slug>[\w-]+)/(?P<number>\d+)/$', + display_item, name='display-item'), +]
\ No newline at end of file diff --git a/showcase/views.py b/showcase/views.py new file mode 100644 index 0000000..7134830 --- /dev/null +++ b/showcase/views.py @@ -0,0 +1,30 @@ +from django.http import Http404, HttpResponse +from django.template import TemplateDoesNotExist +from django.template.loader import get_template +from django.utils.translation import ugettext_lazy as _ + +from .models import ShowCase + + +def display_item(request, slug, number): + q = ShowCase.objects.filter(slug=slug) + if not q.count(): + return Http404(_("Unknown source.")) + showcase = q.all()[0] + source = showcase.external_source + template_name = "showcase/item-{}.html".format(source.source_type.slug) + try: + template = get_template(template_name) + except TemplateDoesNotExist: + raise Http404( + str(_("Template {} is not defined. Ask your administrator to " + "define a template for this source type.")).format( + template_name)) + data = source.get_item(int(number)) + if not data: + raise Http404( + str(_("Data unavailable")) + ) + data["showcase"] = slug + return HttpResponse(template.render(data, request)) + diff --git a/showcase/wagtail_hooks.py b/showcase/wagtail_hooks.py new file mode 100644 index 0000000..86690df --- /dev/null +++ b/showcase/wagtail_hooks.py @@ -0,0 +1,33 @@ +from django.utils.translation import ugettext_lazy as _ + +from wagtail.contrib.modeladmin.options import ( + ModelAdmin, modeladmin_register) + +from .models import ExternalSource, ExternalSourceType + + +class ExternalSourceTypeAdmin(ModelAdmin): + model = ExternalSourceType + menu_label = _("External source types") + menu_icon = 'cogs' + menu_order = 700 + add_to_settings_menu = True + exclude_from_explorer = True + list_display = ('name', 'slug') + + +modeladmin_register(ExternalSourceTypeAdmin) + + +class ExternalSourceAdmin(ModelAdmin): + model = ExternalSource + menu_label = _("External sources") + menu_icon = 'site' + menu_order = 400 + add_to_settings_menu = False + exclude_from_explorer = False + list_display = ('name', 'slug', 'source_type', 'error') + search_fields = ('name',) + + +modeladmin_register(ExternalSourceAdmin) |