├── .editorconfig
├── .env.dist
├── .gitignore
├── Makefile
├── README.md
├── cms
├── Dockerfile
├── __init__.py
├── api
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── models.py
│ ├── schema.py
│ ├── tests.py
│ └── views.py
├── cards
│ ├── __init__.py
│ ├── apps.py
│ ├── management
│ │ ├── __init__.py
│ │ └── commands
│ │ │ ├── __init__.py
│ │ │ ├── create_superuser.py
│ │ │ └── delete_all_wagtail_images.py
│ ├── migrations
│ │ ├── 0001_initial.py
│ │ └── __init__.py
│ ├── models.py
│ ├── static
│ │ └── css
│ │ │ └── welcome_page.css
│ └── wagtail_hooks.py
├── cms
│ ├── __init__.py
│ ├── settings.py
│ ├── static
│ │ └── .gitkeep
│ ├── templates
│ │ ├── 404.html
│ │ ├── 500.html
│ │ └── base.html
│ ├── urls.py
│ └── wsgi.py
├── entrypoint.sh
├── manage.py
├── requirements.txt
├── search
│ ├── __init__.py
│ └── views.py
└── wait_for_postgres.py
├── docker-compose.yml
└── web_frontend
├── .dockerignore
├── .editorconfig
├── .eslintrc.js
├── .gitignore
├── .prettierrc
├── Dockerfile
├── README.md
├── assets
├── README.md
└── css
│ └── tailwind.css
├── components
├── InfoCard
│ └── index.vue
└── README.md
├── jsconfig.json
├── layouts
├── README.md
└── default.vue
├── middleware
└── README.md
├── nuxt.config.js
├── package.json
├── pages
├── README.md
├── entry
│ └── _id.vue
└── index.vue
├── plugins
├── README.md
├── apollo-error-handler.js
├── apollo-watch-loading-handler.js
├── default-apollo-config.js
└── v-body-scroll-lock.js
├── static
└── favicon
│ ├── android-icon-144x144.png
│ ├── android-icon-192x192.png
│ ├── android-icon-36x36.png
│ ├── android-icon-48x48.png
│ ├── android-icon-72x72.png
│ ├── android-icon-96x96.png
│ ├── apple-icon-114x114.png
│ ├── apple-icon-120x120.png
│ ├── apple-icon-144x144.png
│ ├── apple-icon-152x152.png
│ ├── apple-icon-180x180.png
│ ├── apple-icon-57x57.png
│ ├── apple-icon-60x60.png
│ ├── apple-icon-72x72.png
│ ├── apple-icon-76x76.png
│ ├── apple-icon-precomposed.png
│ ├── apple-icon.png
│ ├── browserconfig.xml
│ ├── favicon-16x16.png
│ ├── favicon-32x32.png
│ ├── favicon-96x96.png
│ ├── favicon.ico
│ ├── manifest.json
│ ├── ms-icon-144x144.png
│ ├── ms-icon-150x150.png
│ ├── ms-icon-310x310.png
│ └── ms-icon-70x70.png
├── tailwind.config.js
└── yarn.lock
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig is awesome: https://EditorConfig.org
2 |
3 | root = true
4 |
5 | [*]
6 | charset = utf-8
7 | indent_style = space
8 | indent_size = 2
9 | insert_final_newline = true
10 | trim_trailing_whitespace = true
11 |
12 | [*.{ts,js,py}]
13 | quote_type = single
14 |
15 | [*.py]
16 | indent_style = space
17 | indent_size = 4
18 | max_line_length = 120
19 |
20 | [pep8]
21 | # ignore = E226,E302,E41
22 | max-line-length = 120
23 | indent-size = 2
24 |
25 | [*.md]
26 | max_line_length = off
27 | trim_trailing_whitespace = false
28 |
29 | [Makefile]
30 | indent_style = tab
31 |
32 | [{package.json,.gitlab-ci.yml, docker-compose*.yml}]
33 | indent_style = space
34 | indent_size = 2
35 |
--------------------------------------------------------------------------------
/.env.dist:
--------------------------------------------------------------------------------
1 | DJANGO_SECRET_KEY=local
2 | POSTGRES_USER=root
3 | POSTGRES_PASSWORD=root
4 | POSTGRES_DB=cms
5 | DJANGO_SETTINGS_MODULE=cms.settings
6 | WAGTAIL_ADMIN_USER=root
7 | WAGTAIL_ADMIN_PASSWORD=root
8 | MINIO_ACCESS_KEY=root
9 | MINIO_SECRET_KEY=rootroot
10 | MINIO_BROWSER=on
11 | MINIO_ENDPOINT=127.0.0.1:9000
12 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | **/**/node_modules
2 | **/**/__pycache__
3 | misc/
4 | cms/media/
5 | **/**/.DS_Store
6 | .env
7 | .vscode/
8 | .idea/
9 | **/**/.mypy_cache/
10 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | install:
2 | docker-compose exec cms bash -c 'pip install -r requirements.txt'
3 |
4 | install_web_frontend:
5 | docker-compose run --rm web_frontend bash -c 'rm -fr node_modules && yarn install --force'
6 |
7 | migrate:
8 | docker-compose exec cms bash -c 'python manage.py makemigrations'
9 | docker-compose exec cms bash -c 'python manage.py migrate'
10 |
11 | createsuperuser:
12 | docker-compose exec cms bash -c "python manage.py createsuperuser"
13 |
14 | backup:
15 | docker-compose exec cms bash -c 'python manage.py dumpdata --natural-foreign --indent 2 \
16 | -e contenttypes -e auth.permission \
17 | -e wagtailcore.groupcollectionpermission \
18 | -e wagtailcore.grouppagepermission -e wagtailimages.rendition \
19 | -e sessions -e wagtailcore.site > fixtures.json'
20 |
21 | load:
22 | docker-compose exec cms bash -c 'python manage.py loaddata fixtures.json'
23 |
24 |
25 | deletewagtailimages:
26 | docker-compose exec cms bash -c 'python manage.py delete_all_wagtail_images'
27 |
28 |
29 | initial: migrate createsuperuser
30 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | # Table of Contents
3 |
4 | 1. [Requirements](#org98at330)
5 | 2. [Local Setup](#org57856e7)
6 | 1. [Endpoints](#org809e937)
7 | 1. [Frontend - Nuxt](#orgc37a804)
8 | 2. [Backend - Admin](#org211c10f)
9 | 3. [GraphQL - GraphiQL](#orgc70d5b5)
10 | 4. [Static Files - MinIO](#org8110bc6)
11 | 2. [Credentials](#org749259c)
12 | 1. [DB - Postgre](#orgc6c10a9)
13 | 2. [Backend - Admin](#orge1ac287)
14 | 3. [Static Files - MinIO](#orgc1fcbcb)
15 | 3. [Branding](#org13fa485)
16 | 4. [Frontend](#orgc473881)
17 | 5. [Administration](#orgbf9c4d0)
18 | 1. [Delete all Wagtail Images](#orgf36cc02)
19 | 2. [Migrate Changes](#org2525778)
20 | 3. [Persist Data](#org0ac7a34)
21 |
22 |
23 |
24 |
25 |
26 |
27 | # Requirements
28 |
29 | You need to have [docker](https://docs.docker.com/get-docker/) and preferely docker-compose installed on your system.
30 |
31 |
32 |
33 |
34 | # Local Setup
35 |
36 | Follow these steps to set everything up locally on your machine
37 |
38 | 1. Clone repo
39 |
40 | git clone https://gitlab.com/devs-group/base-wagtail.git && cd base-wagtail
41 |
42 | 2. Copy [.env.dist](.env.dist) to .env
43 |
44 | cp .env.dist .env
45 |
46 | 3. Install node modules
47 |
48 | cd web_frontend
49 | yarn install
50 |
51 | 4. Start Containers with docker-compose
52 |
53 | docker-compose up -d
54 |
55 |
56 |
57 |
58 | ## Endpoints
59 |
60 | As soon as everything is up and running visit these addresses to interact with
61 | the provided APIs, where necessary use [Credentials](#org749259c).
62 |
63 |
64 |
65 |
66 | ### Frontend - Nuxt
67 |
68 |
69 |
70 |
71 |
72 |
73 | ### Backend - Admin
74 |
75 |
76 |
77 |
78 |
79 |
80 | ### GraphQL - GraphiQL
81 |
82 |
83 |
84 |
85 |
86 | ### Static Files - MinIO
87 |
88 |
89 |
90 |
91 |
92 |
93 | ## Credentials
94 |
95 | Default Credentials for the dev setup containing only insensitive test data.
96 | It is advised to change these in the .env.dist and .env files.
97 |
98 |
99 |
100 |
101 | ### DB - Postgre
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 | database |
114 | cms |
115 |
116 |
117 |
118 |
119 | user |
120 | root |
121 |
122 |
123 |
124 |
125 | password |
126 | root |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 | ### Backend - Admin
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 | user |
147 | root |
148 |
149 |
150 |
151 |
152 | password |
153 | root |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 | ### Static Files - MinIO
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 | access-key |
174 | root |
175 |
176 |
177 |
178 |
179 | secret-key |
180 | rootroot |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 | # Branding
189 |
190 | Search the project for strings starting with "PLACEHOLDER_" and exchange to enable custom branding of the admin panel and more.
191 |
192 |
193 |
194 |
195 | # Frontend
196 |
197 | Details concerning the nuxt instance serving the frontend can be found in its own [README](web_frontend/README.md)
198 |
199 |
200 |
201 |
202 | # Administration
203 |
204 | To interface with the containers, a Makefile is provided which provides additional
205 | management commands to the [default django-admin commands](https://docs.djangoproject.com/en/3.0/ref/django-admin/).
206 |
207 |
208 |
209 |
210 | ## Delete all Wagtail Images
211 |
212 | If there is a `key not found` error due to a dead reference, wagtail images might be the problem.
213 | It usually helps to delete all instances of the `wagtail.images.Image` class.
214 | This make command shortens the procedure:
215 |
216 | make deletewagtailimages
217 |
218 |
219 |
220 |
221 | ## Migrate Changes
222 |
223 | To shorten the migration process after a database relevant change was made use:
224 |
225 | make migrate
226 |
227 | This will execute inside the container the commands `./manage.py makemigrations` and `./manage.py migrate`
228 |
229 |
230 |
231 |
232 | ## Persist Data
233 |
234 | To be able to work with data from a different docker volume, fixtures can be created with:
235 |
236 | make backup
237 |
238 | To load the fixtures us:
239 |
240 | make load
241 |
242 |
243 |
244 |
--------------------------------------------------------------------------------
/cms/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.7
2 | # LABEL maintainer="PLACEHOLDER@E.MAIL"
3 | LABEL maintainer="vincent@devs-group.com"
4 |
5 | ENV PYTHONUNBUFFERED 1
6 | ENV DJANGO_ENV dev
7 |
8 | COPY ./entrypoint.sh /usr/local/bin
9 |
10 | WORKDIR /app
11 | COPY ./ /app
12 |
13 | # Install any needed packages specified in requirements.txt
14 | COPY ./requirements.txt ./requirements.txt
15 | RUN pip install --upgrade pip
16 | RUN pip install -r requirements.txt
17 |
18 | CMD ["/usr/local/bin/entrypoint.sh"]
19 |
--------------------------------------------------------------------------------
/cms/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devs-group/wagtail-nuxt/21966fe77c7b07750c7f0c09cb65fff77d2f05ce/cms/__init__.py
--------------------------------------------------------------------------------
/cms/api/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devs-group/wagtail-nuxt/21966fe77c7b07750c7f0c09cb65fff77d2f05ce/cms/api/__init__.py
--------------------------------------------------------------------------------
/cms/api/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 |
3 | # Register your models here.
4 |
--------------------------------------------------------------------------------
/cms/api/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class ApiConfig(AppConfig):
5 | name = 'api'
6 |
--------------------------------------------------------------------------------
/cms/api/models.py:
--------------------------------------------------------------------------------
1 | from django.db import models
2 |
3 | # Create your models here.
4 |
--------------------------------------------------------------------------------
/cms/api/schema.py:
--------------------------------------------------------------------------------
1 | import graphene
2 | from cards.models import InfoCard
3 | from graphene_django import DjangoObjectType
4 |
5 |
6 | class InfoCardNode(DjangoObjectType):
7 | image = graphene.String(width=graphene.Int())
8 |
9 | def resolve_image(self, info, width=860):
10 | if not self.image:
11 | return ""
12 |
13 | return self.image.get_rendition('width-%s' % width).url
14 |
15 | class Meta:
16 | model = InfoCard
17 |
18 |
19 | class Query(graphene.ObjectType):
20 | info_card = graphene.Field(InfoCardNode, id=graphene.Int())
21 | info_cards = graphene.List(InfoCardNode)
22 |
23 | def resolve_info_card(self, info, id):
24 | return InfoCard.objects.get(pk=id)
25 |
26 | def resolve_info_cards(self, info):
27 | return InfoCard.objects.all()
28 |
29 |
30 | schema = graphene.Schema(query=Query)
31 |
--------------------------------------------------------------------------------
/cms/api/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | # Create your tests here.
4 |
--------------------------------------------------------------------------------
/cms/api/views.py:
--------------------------------------------------------------------------------
1 | from django.shortcuts import render
2 |
3 | # Create your views here.
4 |
--------------------------------------------------------------------------------
/cms/cards/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devs-group/wagtail-nuxt/21966fe77c7b07750c7f0c09cb65fff77d2f05ce/cms/cards/__init__.py
--------------------------------------------------------------------------------
/cms/cards/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class CardsConfig(AppConfig):
5 | name = 'cards'
6 |
--------------------------------------------------------------------------------
/cms/cards/management/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devs-group/wagtail-nuxt/21966fe77c7b07750c7f0c09cb65fff77d2f05ce/cms/cards/management/__init__.py
--------------------------------------------------------------------------------
/cms/cards/management/commands/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devs-group/wagtail-nuxt/21966fe77c7b07750c7f0c09cb65fff77d2f05ce/cms/cards/management/commands/__init__.py
--------------------------------------------------------------------------------
/cms/cards/management/commands/create_superuser.py:
--------------------------------------------------------------------------------
1 | from django.contrib.auth import get_user_model
2 | from django.core.management.base import BaseCommand
3 |
4 |
5 | class Command(BaseCommand):
6 | help = 'Create a test super user with the given password'
7 |
8 | def add_arguments(self, parser):
9 | parser.add_argument('username', type=str)
10 | parser.add_argument('password', type=str)
11 |
12 | def handle(self, *args, **options):
13 | username = options.get('username')
14 | password = options.get('password')
15 | try:
16 | User = get_user_model()
17 | if not User.objects.filter(username=username).exists():
18 | User.objects.create_superuser(username,
19 | 'admin@example.com',
20 | password)
21 | print('Superuser %s with password %s successfully created!\n'
22 | % (username, password))
23 | else:
24 | print('Superuser %s with password %s already exists!\n'
25 | % (username, password))
26 | except Exception as e:
27 | print('ERROR: Can\'t create superuser.\n%s\n' % e)
28 |
--------------------------------------------------------------------------------
/cms/cards/management/commands/delete_all_wagtail_images.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | from django.core.management.base import BaseCommand
4 | from wagtail.images.models import Image
5 |
6 |
7 | class Command(BaseCommand):
8 | help = 'For local development delete all linked wagtail images to prevent key: message error. You will be prompted.'
9 |
10 | def yes_or_no(self, question):
11 | reply = str(input(question + ' (y/n): ')).lower().strip()
12 | if reply[0] == 'y':
13 | return True
14 | if reply[0] == 'n':
15 | return False
16 | else:
17 | return self.yes_or_no("Invalid input: %s" % (question))
18 |
19 | def handle(self, *args, **options):
20 | images = Image.objects.all()
21 | if not images:
22 | print("No wagtail images found to delete.")
23 | return
24 |
25 | if self.yes_or_no('Are you sure you want to delete %d wagtail images?' % (len(images))):
26 | try:
27 | Image.objects.all().delete()
28 | except Exception as e:
29 | print('ERROR: Can\'t delete wagtail images.\n%s\n' % e)
30 |
--------------------------------------------------------------------------------
/cms/cards/migrations/0001_initial.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.2.12 on 2020-05-12 10:11
2 |
3 | from django.db import migrations, models
4 | import django.db.models.deletion
5 | import wagtail.core.fields
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | initial = True
11 |
12 | dependencies = [
13 | ('wagtailimages', '0022_uploadedimage'),
14 | ]
15 |
16 | operations = [
17 | migrations.CreateModel(
18 | name='InfoCard',
19 | fields=[
20 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
21 | ('title', models.CharField(max_length=254)),
22 | ('info', wagtail.core.fields.RichTextField(blank=True)),
23 | ('image', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailimages.Image', verbose_name='Image')),
24 | ],
25 | ),
26 | ]
27 |
--------------------------------------------------------------------------------
/cms/cards/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devs-group/wagtail-nuxt/21966fe77c7b07750c7f0c09cb65fff77d2f05ce/cms/cards/migrations/__init__.py
--------------------------------------------------------------------------------
/cms/cards/models.py:
--------------------------------------------------------------------------------
1 | from django.db import models
2 | from wagtail.admin.edit_handlers import FieldPanel
3 | from wagtail.core.fields import RichTextField
4 | from wagtail.core.models import Page
5 | from wagtail.images.edit_handlers import ImageChooserPanel
6 |
7 |
8 | class InfoCard(models.Model):
9 | title = models.CharField(max_length=254)
10 | info = RichTextField(blank=True)
11 | image = models.ForeignKey('wagtailimages.Image', on_delete=models.SET_NULL,
12 | verbose_name='Image', related_name='+',
13 | null=True, blank=True)
14 |
15 | panels = [
16 | FieldPanel('title'),
17 | FieldPanel('info', classname='full'),
18 | ImageChooserPanel('image')
19 | ]
20 |
21 | def __str__(self):
22 | return self.title
23 |
--------------------------------------------------------------------------------
/cms/cards/static/css/welcome_page.css:
--------------------------------------------------------------------------------
1 | html {
2 | box-sizing: border-box;
3 | }
4 |
5 | *,
6 | *:before,
7 | *:after {
8 | box-sizing: inherit;
9 | }
10 |
11 | body {
12 | max-width: 960px;
13 | min-height: 100vh;
14 | margin: 0 auto;
15 | padding: 0 15px;
16 | color: #231f20;
17 | font-family: 'Helvetica Neue', 'Segoe UI', Arial, sans-serif;
18 | line-height: 1.25;
19 | }
20 |
21 | a {
22 | background-color: transparent;
23 | color: #308282;
24 | text-decoration: underline;
25 | }
26 |
27 | a:hover {
28 | color: #ea1b10;
29 | }
30 |
31 | h1,
32 | h2,
33 | h3,
34 | h4,
35 | h5,
36 | p,
37 | ul {
38 | padding: 0;
39 | margin: 0;
40 | font-weight: 400;
41 | }
42 |
43 | main {
44 | display: block; /* For IE11 support */
45 | }
46 |
47 | svg:not(:root) {
48 | overflow: hidden;
49 | }
50 |
51 | .header {
52 | display: flex;
53 | justify-content: space-between;
54 | align-items: center;
55 | padding-top: 20px;
56 | padding-bottom: 10px;
57 | border-bottom: 1px solid #e6e6e6;
58 | }
59 |
60 | .logo {
61 | width: 150px;
62 | margin-right: 20px;
63 | }
64 |
65 | .logo a {
66 | display: block;
67 | }
68 |
69 | .figure-logo {
70 | max-width: 150px;
71 | max-height: 55.1px;
72 | }
73 |
74 | .release-notes {
75 | font-size: 14px;
76 | }
77 |
78 | .main {
79 | padding: 40px 0;
80 | margin: 0 auto;
81 | text-align: center;
82 | }
83 |
84 | .figure-space {
85 | max-width: 265px;
86 | }
87 |
88 | @-webkit-keyframes pos {
89 | 0%, 100% {
90 | -webkit-transform: rotate(-6deg);
91 | transform: rotate(-6deg);
92 | }
93 | 50% {
94 | -webkit-transform: rotate(6deg);
95 | transform: rotate(6deg);
96 | }
97 | }
98 |
99 | @keyframes pos {
100 | 0%, 100% {
101 | -webkit-transform: rotate(-6deg);
102 | transform: rotate(-6deg);
103 | }
104 | 50% {
105 | -webkit-transform: rotate(6deg);
106 | transform: rotate(6deg);
107 | }
108 | }
109 |
110 | .egg {
111 | fill: #43b1b0;
112 | -webkit-animation: pos 3s ease infinite;
113 | animation: pos 3s ease infinite;
114 | -webkit-transform: translateY(50px);
115 | transform: translateY(50px);
116 | -webkit-transform-origin: 50% 80%;
117 | transform-origin: 50% 80%;
118 | }
119 |
120 | .main-text {
121 | max-width: 400px;
122 | margin: 5px auto;
123 | }
124 |
125 | .main-text h1 {
126 | font-size: 22px;
127 | }
128 |
129 | .main-text p {
130 | margin: 15px auto 0;
131 | }
132 |
133 | .footer {
134 | display: flex;
135 | flex-wrap: wrap;
136 | justify-content: space-between;
137 | border-top: 1px solid #e6e6e6;
138 | padding: 10px;
139 | }
140 |
141 | .option {
142 | display: block;
143 | padding: 10px 10px 10px 34px;
144 | position: relative;
145 | text-decoration: none;
146 | }
147 |
148 | .option svg {
149 | width: 24px;
150 | height: 24px;
151 | fill: gray;
152 | border: 1px solid #d9d9d9;
153 | padding: 5px;
154 | border-radius: 100%;
155 | top: 10px;
156 | left: 0;
157 | position: absolute;
158 | }
159 |
160 | .option h4 {
161 | font-size: 19px;
162 | text-decoration: underline;
163 | }
164 |
165 | .option p {
166 | padding-top: 3px;
167 | color: #231f20;
168 | font-size: 15px;
169 | font-weight: 300;
170 | }
171 |
172 | @media (max-width: 996px) {
173 | body {
174 | max-width: 780px;
175 | }
176 | }
177 |
178 | @media (max-width: 767px) {
179 | .option {
180 | flex: 0 0 50%;
181 | }
182 | }
183 |
184 | @media (max-width: 599px) {
185 | .main {
186 | padding: 20px 0;
187 | }
188 |
189 | .figure-space {
190 | max-width: 200px;
191 | }
192 |
193 | .footer {
194 | display: block;
195 | width: 300px;
196 | margin: 0 auto;
197 | }
198 | }
199 |
200 | @media (max-width: 360px) {
201 | .header-link {
202 | max-width: 100px;
203 | }
204 | }
205 |
--------------------------------------------------------------------------------
/cms/cards/wagtail_hooks.py:
--------------------------------------------------------------------------------
1 | from cards.models import InfoCard
2 | from wagtail.contrib.modeladmin.options import ModelAdmin, modeladmin_register
3 |
4 |
5 | class InfoCardAdminMenu(ModelAdmin):
6 | model = InfoCard
7 | menu_icon = 'form'
8 | menu_label = 'Info Card'
9 | search_fields = ('title',)
10 |
11 |
12 | # -------------------- Register Buttons in admin panel --------------------
13 | modeladmin_register(InfoCardAdminMenu)
14 |
--------------------------------------------------------------------------------
/cms/cms/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devs-group/wagtail-nuxt/21966fe77c7b07750c7f0c09cb65fff77d2f05ce/cms/cms/__init__.py
--------------------------------------------------------------------------------
/cms/cms/settings.py:
--------------------------------------------------------------------------------
1 | """
2 | Django settings for COOKIECUTTER_PLACEHOLDER_PROJECTNAME project.
3 |
4 | Generated by 'django-admin startproject' using Django 2.2.8.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/2.2/topics/settings/
8 |
9 | For the full list of settings and their values, see
10 | https://docs.djangoproject.com/en/2.2/ref/settings/
11 | """
12 |
13 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
14 | import os
15 |
16 | PROJECT_DIR = os.path.dirname(os.path.abspath(__file__))
17 | BASE_DIR = os.path.dirname(PROJECT_DIR)
18 |
19 | # Quick-start development settings - unsuitable for production
20 | # See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/
21 |
22 |
23 | # Application definition
24 |
25 | INSTALLED_APPS = [
26 |
27 | 'cards',
28 | 'search',
29 | 'api',
30 |
31 | 'corsheaders',
32 |
33 | 'wagtail.api.v2',
34 | 'wagtail.contrib.forms',
35 | 'wagtail.contrib.modeladmin',
36 | 'wagtail.contrib.redirects',
37 | 'wagtail.contrib.styleguide',
38 | 'wagtail.embeds',
39 | 'wagtail.sites',
40 | 'wagtail.users',
41 | 'wagtail.snippets',
42 | 'wagtail.documents',
43 | 'wagtail.images',
44 | 'wagtail.search',
45 | 'wagtail.admin',
46 | 'wagtail.core',
47 |
48 | 'modelcluster',
49 | 'taggit',
50 | 'wagtailmenus',
51 |
52 | 'wagtail_graphql',
53 | 'graphene_django',
54 |
55 | 'django.contrib.admin',
56 | 'django.contrib.auth',
57 | 'django.contrib.contenttypes',
58 | 'django.contrib.sessions',
59 | 'django.contrib.messages',
60 | 'django.contrib.staticfiles',
61 | ]
62 |
63 | MIDDLEWARE = [
64 | 'django.contrib.sessions.middleware.SessionMiddleware',
65 |
66 | 'corsheaders.middleware.CorsMiddleware',
67 | 'django.middleware.common.CommonMiddleware',
68 | 'django.middleware.csrf.CsrfViewMiddleware',
69 | 'django.contrib.auth.middleware.AuthenticationMiddleware',
70 | 'django.contrib.messages.middleware.MessageMiddleware',
71 | 'django.middleware.clickjacking.XFrameOptionsMiddleware',
72 | 'django.middleware.security.SecurityMiddleware',
73 |
74 | 'wagtail.core.middleware.SiteMiddleware',
75 | 'wagtail.contrib.redirects.middleware.RedirectMiddleware',
76 | ]
77 |
78 | ROOT_URLCONF = 'cms.urls'
79 |
80 | TEMPLATES = [
81 | {
82 | 'BACKEND': 'django.template.backends.django.DjangoTemplates',
83 | 'DIRS': [
84 | os.path.join(PROJECT_DIR, 'templates'),
85 | ],
86 | 'APP_DIRS': True,
87 | 'OPTIONS': {
88 | 'context_processors': [
89 | 'django.template.context_processors.debug',
90 | 'django.template.context_processors.request',
91 | 'django.contrib.auth.context_processors.auth',
92 | 'django.contrib.messages.context_processors.messages',
93 | 'wagtailmenus.context_processors.wagtailmenus',
94 | ],
95 | },
96 | },
97 | ]
98 |
99 | GRAPHENE = {
100 | 'SCHEMA': 'api.schema.schema',
101 | }
102 |
103 | GRAPHQL_API = {
104 | 'APPS': [
105 | 'cards',
106 | ]
107 | }
108 |
109 | WSGI_APPLICATION = 'cms.wsgi.application'
110 |
111 | # Password validation
112 | # https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators
113 |
114 | AUTH_PASSWORD_VALIDATORS = [
115 | {
116 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
117 | },
118 | {
119 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
120 | },
121 | {
122 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
123 | },
124 | {
125 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
126 | },
127 | ]
128 |
129 | # Static files (CSS, JavaScript, Images)
130 | # https://docs.djangoproject.com/en/2.2/howto/static-files/
131 | TIME_ZONE = 'UTC'
132 |
133 | STATIC_URL = '/static/'
134 | STATIC_ROOT = './static_files/'
135 |
136 | STATICFILES_DIRS = [
137 | os.path.join(PROJECT_DIR, 'static'),
138 | ]
139 |
140 | STATICFILES_FINDERS = [
141 | 'django.contrib.staticfiles.finders.FileSystemFinder',
142 | 'django.contrib.staticfiles.finders.AppDirectoriesFinder',
143 | ]
144 |
145 | DEFAULT_FILE_STORAGE = "minio_storage.storage.MinioMediaStorage"
146 | STATICFILES_STORAGE = "minio_storage.storage.MinioStaticStorage"
147 | MINIO_STORAGE_ENDPOINT = 'minio:9000'
148 | MINIO_STORAGE_STATIC_URL = '//%s/local-static/' % (
149 | os.environ.get('MINIO_ENDPOINT'))
150 | MINIO_STORAGE_MEDIA_URL = '//%s/local-media/' % (
151 | os.environ.get('MINIO_ENDPOINT'))
152 | MINIO_STORAGE_ACCESS_KEY = os.environ.get('MINIO_ACCESS_KEY')
153 | MINIO_STORAGE_SECRET_KEY = os.environ.get('MINIO_SECRET_KEY')
154 | MINIO_STORAGE_USE_HTTPS = False
155 | MINIO_STORAGE_MEDIA_BUCKET_NAME = 'local-media'
156 | MINIO_STORAGE_AUTO_CREATE_MEDIA_BUCKET = True
157 | MINIO_STORAGE_STATIC_BUCKET_NAME = 'local-static'
158 | MINIO_STORAGE_AUTO_CREATE_STATIC_BUCKET = True
159 |
160 | MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
161 | MEDIA_URL = '/media/'
162 |
163 | # Wagtail settings
164 |
165 | WAGTAIL_SITE_NAME = "cms"
166 |
167 | # Base URL to use when referring to full URLs within the Wagtail admin backend -
168 | # e.g. in notification emails. Don't include '/admin' or a trailing slash
169 | BASE_URL = 'http://example.com'
170 |
171 | CORS_ORIGIN_ALLOW_ALL = True
172 | CORS_ALLOW_CREDENTIALS = True
173 |
174 | # SECURITY WARNING: don't run with debug turned on in production!
175 | DEBUG = True
176 | ENABLE_DEBUG_BAR = False
177 | WAGTAIL_CACHE = True
178 |
179 | # SECURITY WARNING: keep the secret key used in production secret!
180 | SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY')
181 |
182 | # SECURITY WARNING: define the correct hosts in production!
183 | ALLOWED_HOSTS = ['*']
184 |
185 | EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
186 |
187 | # Database
188 | # https://docs.djangoproject.com/en/2.2/ref/settings/#databases
189 |
190 |
191 | if ENABLE_DEBUG_BAR is True and DEBUG is True:
192 |
193 | INSTALLED_APPS = INSTALLED_APPS + [
194 | 'debug_toolbar',
195 | ]
196 |
197 | MIDDLEWARE = MIDDLEWARE + [
198 | 'debug_toolbar.middleware.DebugToolbarMiddleware',
199 | ]
200 |
201 | # Postgres
202 | DATABASES = {
203 | 'default': {
204 | 'ENGINE': 'django.db.backends.postgresql_psycopg2',
205 | 'NAME': os.environ.get('POSTGRES_DB'),
206 | 'USER': os.environ.get('POSTGRES_USER'),
207 | 'PASSWORD': os.environ.get('POSTGRES_PASSWORD'),
208 | 'HOST': 'postgres',
209 | 'PORT': '5432',
210 | }
211 | }
212 |
213 | INTERNAL_IPS = ("127.0.0.1", "172.17.0.1", "172.28.0.1")
214 |
215 | try:
216 | from .local import *
217 | except ImportError:
218 | pass
219 |
--------------------------------------------------------------------------------
/cms/cms/static/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devs-group/wagtail-nuxt/21966fe77c7b07750c7f0c09cb65fff77d2f05ce/cms/cms/static/.gitkeep
--------------------------------------------------------------------------------
/cms/cms/templates/404.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 |
3 | {% block body_class %}template-404{% endblock %}
4 |
5 | {% block content %}
6 | Page not found
7 |
8 | Sorry, this page could not be found.
9 | {% endblock %}
10 |
--------------------------------------------------------------------------------
/cms/cms/templates/500.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Internal server error
6 |
7 |
8 |
9 | Internal server error
10 |
11 | Sorry, there seems to be an error. Please try again soon.
12 |
13 |
14 |
--------------------------------------------------------------------------------
/cms/cms/templates/base.html:
--------------------------------------------------------------------------------
1 | {% load static wagtailuserbar %}
2 |
3 |
4 |
5 |
6 |
7 |
8 | {% block title %}
9 | {% if self.seo_title %}{{ self.seo_title }}{% else %}{{ self.title }}{% endif %}
10 | {% endblock %}
11 | {% block title_suffix %}
12 | {% with self.get_site.site_name as site_name %}
13 | {% if site_name %}- {{ site_name }}{% endif %}
14 | {% endwith %}
15 | {% endblock %}
16 |
17 |
18 |
19 |
20 | {# Global stylesheets #}
21 |
22 |
23 | {% block extra_css %}
24 | {# Override this in templates to add extra stylesheets #}
25 | {% endblock %}
26 |
27 |
28 |
29 | {% wagtailuserbar %}
30 |
31 | {% block content %}{% endblock %}
32 |
33 | {# Global javascript #}
34 |
35 |
36 | {% block extra_js %}
37 | {# Override this in templates to add extra javascript #}
38 | {% endblock %}
39 |
40 |
41 |
--------------------------------------------------------------------------------
/cms/cms/urls.py:
--------------------------------------------------------------------------------
1 | from django.conf import settings
2 | from django.conf.urls import include, url
3 | from django.contrib import admin
4 | from django.urls import path
5 | from django.views.decorators.csrf import csrf_exempt
6 | from graphene_django.views import GraphQLView
7 | from search import views as search_views
8 | from wagtail.admin import urls as wagtailadmin_urls
9 | from wagtail.core import urls as wagtail_urls
10 | from wagtail.documents import urls as wagtaildocs_urls
11 | from wagtail.images.views.serve import ServeView
12 |
13 | urlpatterns = [
14 | url(r'^django-admin/', admin.site.urls),
15 | url(r'^admin/', include(wagtailadmin_urls)),
16 | url(r'^documents/', include(wagtaildocs_urls)),
17 | url(r'^api/graphql', csrf_exempt(GraphQLView.as_view())),
18 | url(r'^api/graphiql', csrf_exempt(GraphQLView.as_view(graphiql=True, pretty=True))),
19 | url(r'', include(wagtail_urls)),
20 | ]
21 |
22 | if settings.DEBUG:
23 | from django.conf.urls.static import static
24 | from django.contrib.staticfiles.urls import staticfiles_urlpatterns
25 | import debug_toolbar
26 |
27 | # Serve static and media files from development server
28 | urlpatterns += staticfiles_urlpatterns()
29 | urlpatterns += static(settings.MEDIA_URL,
30 | document_root=settings.MEDIA_ROOT)
31 |
32 | urlpatterns = [
33 | path('__debug__/', include(debug_toolbar.urls)),
34 | ] + urlpatterns
35 |
--------------------------------------------------------------------------------
/cms/cms/wsgi.py:
--------------------------------------------------------------------------------
1 | """
2 | WSGI config for PLACEHOLDER_PROJECTNAME project.
3 |
4 | It exposes the WSGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/2.2/howto/deployment/wsgi/
8 | """
9 |
10 | import os
11 |
12 | from django.core.wsgi import get_wsgi_application
13 |
14 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "cms.settings")
15 |
16 | application = get_wsgi_application()
17 |
--------------------------------------------------------------------------------
/cms/entrypoint.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | function waitForPostgres() {
4 | echo "Waiting for postgres ..."
5 | python wait_for_postgres.py
6 | }
7 |
8 | function migrateTables() {
9 | echo "Migrating tables..."
10 | python manage.py makemigrations && python manage.py migrate --noinput
11 | }
12 |
13 | function loadStatics() {
14 | echo "Loading static files..."
15 | python manage.py collectstatic --noinput
16 | }
17 |
18 | function loadFixtures() {
19 | echo "Loading fixtures..."
20 | if [ -f fixtures.json ]; then
21 | python manage.py loaddata fixtures.json
22 | fi
23 | }
24 |
25 | function createSuperuser () {
26 | echo "Creating superuser..."
27 | local username="$1"
28 | local password="$2"
29 | python manage.py create_superuser $username $password
30 | }
31 |
32 | function syncPageTranslationFields () {
33 | echo "Syncing page translation fields..."
34 | python manage.py sync_page_translation_fields
35 | }
36 |
37 |
38 | waitForPostgres
39 | migrateTables
40 | loadStatics
41 | createSuperuser $WAGTAIL_ADMIN_USER $WAGTAIL_ADMIN_PASSWORD
42 | gunicorn --bind 0.0.0.0:8000 --reload --workers 3 --worker-class gevent --access-logfile - cms.wsgi:application
43 |
--------------------------------------------------------------------------------
/cms/manage.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | import os
3 | import sys
4 |
5 | if __name__ == "__main__":
6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE",
7 | "cms.settings")
8 |
9 | from django.core.management import execute_from_command_line
10 |
11 | execute_from_command_line(sys.argv)
12 |
--------------------------------------------------------------------------------
/cms/requirements.txt:
--------------------------------------------------------------------------------
1 | Django>=2.2,<2.3
2 | wagtail>=2.9,<3.0
3 | gunicorn==19.9.0
4 | gevent==1.4.0
5 | ipython==7.12.0
6 | django-debug-toolbar
7 |
8 |
9 | # Storage
10 | psycopg2==2.8.3
11 | wagtailmenus>=3.0
12 | django-minio-storage==0.3.5
13 |
14 | # API
15 | wagtail-graphql
16 | graphene-django
17 | django-cors-headers
18 |
--------------------------------------------------------------------------------
/cms/search/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devs-group/wagtail-nuxt/21966fe77c7b07750c7f0c09cb65fff77d2f05ce/cms/search/__init__.py
--------------------------------------------------------------------------------
/cms/search/views.py:
--------------------------------------------------------------------------------
1 | from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator
2 | from django.shortcuts import render
3 |
4 | from wagtail.core.models import Page
5 | from wagtail.search.models import Query
6 |
7 |
8 | def search(request):
9 | search_query = request.GET.get('query', None)
10 | page = request.GET.get('page', 1)
11 |
12 | # Search
13 | if search_query:
14 | search_results = Page.objects.live().search(search_query)
15 | query = Query.get(search_query)
16 |
17 | # Record hit
18 | query.add_hit()
19 | else:
20 | search_results = Page.objects.none()
21 |
22 | # Pagination
23 | paginator = Paginator(search_results, 10)
24 | try:
25 | search_results = paginator.page(page)
26 | except PageNotAnInteger:
27 | search_results = paginator.page(1)
28 | except EmptyPage:
29 | search_results = paginator.page(paginator.num_pages)
30 |
31 | return render(request, 'search/search.html', {
32 | 'search_query': search_query,
33 | 'search_results': search_results,
34 | })
35 |
--------------------------------------------------------------------------------
/cms/wait_for_postgres.py:
--------------------------------------------------------------------------------
1 | import logging
2 | import os
3 | from time import sleep, time
4 |
5 | import psycopg2
6 |
7 | check_timeout = os.getenv("POSTGRES_CHECK_TIMEOUT", 30)
8 | check_interval = os.getenv("POSTGRES_CHECK_INTERVAL", 1)
9 | interval_unit = "second" if check_interval == 1 else "seconds"
10 | config = {
11 | "dbname": os.getenv("POSTGRES_DB", "postgres"),
12 | "user": os.getenv("POSTGRES_USER", "postgres"),
13 | "password": os.getenv("POSTGRES_PASSWORD", ""),
14 | "host": os.getenv("DATABASE_URL", "postgres")
15 | }
16 |
17 | start_time = time()
18 | logger = logging.getLogger()
19 | logger.setLevel(logging.INFO)
20 | logger.addHandler(logging.StreamHandler())
21 |
22 |
23 | def pg_isready(**kwargs):
24 | while time() - start_time < check_timeout:
25 | try:
26 | conn = psycopg2.connect(**kwargs)
27 | logger.info("Postgres is ready! ✨ 💅")
28 | conn.close()
29 | return True
30 | except psycopg2.OperationalError as e:
31 | logger.info(
32 | f"Postgres isn't ready.\n%s\n Waiting for {check_interval} {interval_unit}..." % e)
33 | sleep(check_interval)
34 |
35 | logger.error(
36 | f"We could not connect to Postgres within {check_timeout} seconds.")
37 | return False
38 |
39 |
40 | pg_isready(**config)
41 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: "3"
2 |
3 | volumes:
4 | db:
5 | minio-data:
6 |
7 | networks:
8 | default:
9 | driver: bridge
10 | external: false
11 |
12 | services:
13 | web_frontend:
14 | restart: always
15 | env_file: .env
16 | image: node:12.15.0
17 | working_dir: /app
18 | volumes:
19 | - ./web_frontend:/app
20 | command: "yarn dev"
21 | ports:
22 | - 3000:3000
23 | depends_on:
24 | - cms
25 | links:
26 | - cms
27 |
28 | cms:
29 | restart: always
30 | env_file: .env
31 | build:
32 | context: ./cms
33 | dockerfile: Dockerfile
34 | entrypoint: /usr/bin/entrypoint.sh
35 | working_dir: /app
36 | volumes:
37 | - ./cms:/app
38 | - ./cms/entrypoint.sh:/usr/bin/entrypoint.sh
39 | ports:
40 | - 8000:8000
41 | depends_on:
42 | - postgres
43 | - minio
44 | links:
45 | - postgres
46 | - minio
47 | networks:
48 | - default
49 |
50 | postgres:
51 | image: postgres:9.6
52 | volumes:
53 | - db:/var/lib/postgresql/data
54 | networks:
55 | - default
56 | env_file: .env
57 |
58 | minio:
59 | image: minio/minio:RELEASE.2020-02-07T04-56-50Z
60 | env_file: .env
61 | volumes:
62 | - minio-data:/data
63 | ports:
64 | - 9000:9000
65 | command: server /data
66 |
--------------------------------------------------------------------------------
/web_frontend/.dockerignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/web_frontend/.editorconfig:
--------------------------------------------------------------------------------
1 | # editorconfig.org
2 | root = true
3 |
4 | [*]
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | charset = utf-8
9 | trim_trailing_whitespace = true
10 | insert_final_newline = true
11 |
12 | [*.md]
13 | trim_trailing_whitespace = false
14 |
--------------------------------------------------------------------------------
/web_frontend/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: {
4 | browser: true,
5 | node: true
6 | },
7 | parserOptions: {
8 | parser: 'babel-eslint'
9 | },
10 | extends: [
11 | '@nuxtjs',
12 | 'prettier',
13 | 'prettier/vue',
14 | 'plugin:prettier/recommended',
15 | 'plugin:nuxt/recommended'
16 | ],
17 | plugins: ['prettier'],
18 | // add your custom rules here
19 | rules: {
20 | 'no-console': 'off'
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/web_frontend/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by .ignore support plugin (hsz.mobi)
2 | ### Node template
3 | # Logs
4 | /logs
5 | *.log
6 | npm-debug.log*
7 | yarn-debug.log*
8 | yarn-error.log*
9 |
10 | # Runtime data
11 | pids
12 | *.pid
13 | *.seed
14 | *.pid.lock
15 |
16 | # Directory for instrumented libs generated by jscoverage/JSCover
17 | lib-cov
18 |
19 | # Coverage directory used by tools like istanbul
20 | coverage
21 |
22 | # nyc test coverage
23 | .nyc_output
24 |
25 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
26 | .grunt
27 |
28 | # Bower dependency directory (https://bower.io/)
29 | bower_components
30 |
31 | # node-waf configuration
32 | .lock-wscript
33 |
34 | # Compiled binary addons (https://nodejs.org/api/addons.html)
35 | build/Release
36 |
37 | # Dependency directories
38 | node_modules/
39 | jspm_packages/
40 |
41 | # TypeScript v1 declaration files
42 | typings/
43 |
44 | # Optional npm cache directory
45 | .npm
46 |
47 | # Optional eslint cache
48 | .eslintcache
49 |
50 | # Optional REPL history
51 | .node_repl_history
52 |
53 | # Output of 'npm pack'
54 | *.tgz
55 |
56 | # Yarn Integrity file
57 | .yarn-integrity
58 |
59 | # dotenv environment variables file
60 | .env
61 |
62 | # parcel-bundler cache (https://parceljs.org/)
63 | .cache
64 |
65 | # next.js build output
66 | .next
67 |
68 | # nuxt.js build output
69 | .nuxt
70 |
71 | # Nuxt generate
72 | dist
73 |
74 | # vuepress build output
75 | .vuepress/dist
76 |
77 | # Serverless directories
78 | .serverless
79 |
80 | # IDE / Editor
81 | .idea
82 |
83 | # Service worker
84 | sw.*
85 |
86 | # Mac OSX
87 | .DS_Store
88 |
89 | # Vim swap files
90 | *.swp
91 |
--------------------------------------------------------------------------------
/web_frontend/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "semi": false,
3 | "arrowParens": "always",
4 | "singleQuote": true
5 | }
6 |
--------------------------------------------------------------------------------
/web_frontend/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:12.15.0
2 |
3 | WORKDIR /app
4 | ADD . /app/
5 |
6 | RUN npm i -g yarn --force
7 |
8 | RUN yarn install
9 | RUN yarn build
10 |
11 | CMD [ "yarn", "start" ]
12 |
--------------------------------------------------------------------------------
/web_frontend/README.md:
--------------------------------------------------------------------------------
1 | # web frontend
2 |
3 | > Web Frontend for PLACEHOLDER_PROJECTNAME
4 |
5 | ## Build Setup
6 | *
7 | ``` bash
8 | # install dependencies
9 | $ yarn install
10 |
11 | # serve with hot reload at localhost:3000
12 | $ yarn dev
13 |
14 | # build for production and launch server
15 | $ yarn build
16 | $ yarn start
17 |
18 | # generate static project
19 | $ yarn generate
20 | ```
21 |
22 | For detailed explanation on how things work, check out [Nuxt.js docs](https://nuxtjs.org).
23 |
--------------------------------------------------------------------------------
/web_frontend/assets/README.md:
--------------------------------------------------------------------------------
1 | # ASSETS
2 |
3 | **This directory is not required, you can delete it if you don't want to use it.**
4 |
5 | This directory contains your un-compiled assets such as LESS, SASS, or JavaScript.
6 |
7 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/assets#webpacked).
8 |
--------------------------------------------------------------------------------
/web_frontend/assets/css/tailwind.css:
--------------------------------------------------------------------------------
1 | @import 'tailwindcss/base';
2 | @import 'tailwindcss/components';
3 | @import 'tailwindcss/utilities';
4 |
--------------------------------------------------------------------------------
/web_frontend/components/InfoCard/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
17 |
44 |
--------------------------------------------------------------------------------
/web_frontend/components/README.md:
--------------------------------------------------------------------------------
1 | # COMPONENTS
2 |
3 | **This directory is not required, you can delete it if you don't want to use it.**
4 |
5 | The components directory contains your Vue.js Components.
6 |
7 | _Nuxt.js doesn't supercharge these components._
8 |
--------------------------------------------------------------------------------
/web_frontend/jsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "baseUrl": ".",
4 | "paths": {
5 | "~/*": ["./*"],
6 | "@/*": ["./*"],
7 | "~~/*": ["./*"],
8 | "@@/*": ["./*"]
9 | }
10 | },
11 | "exclude": ["node_modules", ".nuxt", "dist"]
12 | }
13 |
--------------------------------------------------------------------------------
/web_frontend/layouts/README.md:
--------------------------------------------------------------------------------
1 | # LAYOUTS
2 |
3 | **This directory is not required, you can delete it if you don't want to use it.**
4 |
5 | This directory contains your Application Layouts.
6 |
7 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/views#layouts).
8 |
--------------------------------------------------------------------------------
/web_frontend/layouts/default.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
15 |
--------------------------------------------------------------------------------
/web_frontend/middleware/README.md:
--------------------------------------------------------------------------------
1 | # MIDDLEWARE
2 |
3 | **This directory is not required, you can delete it if you don't want to use it.**
4 |
5 | This directory contains your application middleware.
6 | Middleware let you define custom functions that can be run before rendering either a page or a group of pages.
7 |
8 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/routing#middleware).
9 |
--------------------------------------------------------------------------------
/web_frontend/nuxt.config.js:
--------------------------------------------------------------------------------
1 | export default {
2 | mode: 'universal',
3 | server: {
4 | port: 3000,
5 | host: '0.0.0.0'
6 | },
7 | /*
8 | ** Headers of the page
9 | */
10 | head() {
11 | return {
12 | title: 'PLACEHOLDER_PROJECTNAME',
13 | meta: [
14 | { charset: 'utf-8' },
15 | {
16 | name: 'viewport',
17 | content: 'width=device-width, initial-scale=1, maximum-scale=1'
18 | },
19 | {
20 | hid: 'description',
21 | name: 'description',
22 | content: 'meta.description'
23 | }
24 | ],
25 | link: [
26 | { rel: 'icon', type: 'image/x-icon', href: '/favicons/favicon.ico' },
27 | {
28 | rel: 'shortcut icon',
29 | type: 'image/png',
30 | href: '/favicons/icon-192x192.png'
31 | },
32 |
33 | {
34 | rel: 'shortcut icon',
35 | sizes: '192x192',
36 | href: '/favicons/android-icon-192x192.png'
37 | },
38 | {
39 | rel: 'apple-touch-icon',
40 | href: '/favicons/apple-icon-180x180.png'
41 | },
42 | {
43 | rel: 'stylesheet',
44 | href: 'https://use.typekit.net/oft7xcx.css'
45 | }
46 | ]
47 | }
48 | },
49 | /*
50 | ** Customize the progress-bar color
51 | */
52 | loading: { color: '#fff' },
53 | /*
54 | ** Global CSS
55 | */
56 | css: [],
57 | /*
58 | ** Plugins to load before mounting the App
59 | */
60 | plugins: ['~/plugins/v-body-scroll-lock'],
61 | /*
62 | ** Nuxt.js dev-modules
63 | */
64 | buildModules: [
65 | // Doc: https://github.com/nuxt-community/eslint-module
66 | '@nuxtjs/eslint-module',
67 | // Doc: https://github.com/nuxt-community/nuxt-tailwindcss
68 | '@nuxtjs/tailwindcss'
69 | ],
70 | /*
71 | ** Nuxt.js modules
72 | */
73 | modules: [
74 | // Doc: https://axios.nuxtjs.org/usage
75 | '@nuxtjs/axios',
76 | '@nuxtjs/pwa',
77 | // Doc: https://github.com/nuxt-community/dotenv-module
78 | '@nuxtjs/dotenv',
79 | // Docs: https://github.com/nuxt-community/apollo-module
80 | '@nuxtjs/apollo',
81 | ['vue-scrollto/nuxt', { duration: 300 }]
82 | ],
83 | /*
84 | ** Axios module configuration
85 | ** See https://axios.nuxtjs.org/options
86 | */
87 | axios: {},
88 | /*
89 | ** Build configuration
90 | */
91 | build: {
92 | /*
93 | ** You can extend webpack config here
94 | */
95 | extend(config, ctx) {},
96 | transpile: ['v-body-scroll-lock']
97 | },
98 | apollo: {
99 | // tokenName: 'yourApolloTokenName', // optional, default: apollo-token
100 | cookieAttributes: {
101 | /**
102 | * Define when the cookie will be removed. Value can be a Number
103 | * which will be interpreted as days from time of creation or a
104 | * Date instance. If omitted, the cookie becomes a session cookie.
105 | */
106 | expires: 7, // optional, default: 7 (days)
107 |
108 | /**
109 | * Define the path where the cookie is available. Defaults to '/'
110 | */
111 | // path: '/', // optional
112 | /**
113 | * Define the domain where the cookie is available. Defaults to
114 | * the domain of the page where the cookie was created.
115 | */
116 | // domain: 'example.com', // optional
117 |
118 | /**
119 | * A Boolean indicating if the cookie transmission requires a
120 | * secure protocol (https). Defaults to false.
121 | */
122 | secure: false
123 | },
124 | includeNodeModules: true, // optional, default: false (this includes graphql-tag for node_modules folder)
125 | // authenticationType: 'Basic', // optional, default: 'Bearer'
126 | // (Optional) Default 'apollo' definition
127 | defaultOptions: {
128 | // See 'apollo' definition
129 | // For example: default query options
130 | $query: {
131 | loadingKey: 'loading',
132 | fetchPolicy: 'cache-and-network'
133 | }
134 | },
135 | // optional
136 | watchLoading: '~/plugins/apollo-watch-loading-handler.js',
137 | // optional
138 | errorHandler: '~/plugins/apollo-error-handler.js',
139 | // required
140 | clientConfigs: {
141 | default: '~/plugins/default-apollo-config.js'
142 | }
143 | }
144 | }
145 |
--------------------------------------------------------------------------------
/web_frontend/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "web_frontend",
3 | "version": "1.0.0",
4 | "description": "Web Frontend for PLACEHOLDER_PROJECTNAME",
5 | "author": "PLACEHOLDER_AUTHOR",
6 | "private": true,
7 | "scripts": {
8 | "dev": "nuxt",
9 | "build": "nuxt build",
10 | "start": "nuxt start",
11 | "generate": "nuxt generate",
12 | "lint": "eslint --ext .js,.vue --ignore-path .gitignore ."
13 | },
14 | "lint-staged": {
15 | "*.{js,vue}": "eslint"
16 | },
17 | "engines": {
18 | "node": ">=12.15"
19 | },
20 | "husky": {
21 | "hooks": {
22 | "pre-commit": "lint-staged"
23 | }
24 | },
25 | "dependencies": {
26 | "@nuxtjs/apollo": "4.0.0-rc19",
27 | "@nuxtjs/axios": "^5.3.6",
28 | "@nuxtjs/dotenv": "^1.4.0",
29 | "@nuxtjs/pwa": "^3.0.0-0",
30 | "graphql-tag": "2.10.1",
31 | "lodash": "4.17.15",
32 | "mobile-detect": "^1.4.4",
33 | "node-sass": "^4.13.1",
34 | "nuxt": "^2.0.0",
35 | "sass-loader": "^8.0.2",
36 | "v-body-scroll-lock": "^1.1.3",
37 | "vue-scrollto": "^2.17.1"
38 | },
39 | "devDependencies": {
40 | "@nuxtjs/eslint-config": "^1.0.1",
41 | "@nuxtjs/eslint-module": "^1.0.0",
42 | "@nuxtjs/tailwindcss": "^1.0.0",
43 | "babel-eslint": "^10.0.1",
44 | "eslint": "^6.1.0",
45 | "eslint-config-prettier": "^4.1.0",
46 | "eslint-plugin-nuxt": ">=0.4.2",
47 | "eslint-plugin-prettier": "^3.0.1",
48 | "husky": "^2.6.0",
49 | "lint-staged": "^8.2.1",
50 | "prettier": "^1.16.4"
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/web_frontend/pages/README.md:
--------------------------------------------------------------------------------
1 | # PAGES
2 |
3 | This directory contains your Application Views and Routes.
4 | The framework reads all the `*.vue` files inside this directory and creates the router of your application.
5 |
6 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/routing).
7 |
--------------------------------------------------------------------------------
/web_frontend/pages/entry/_id.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
44 |
--------------------------------------------------------------------------------
/web_frontend/pages/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 | {{
6 | infoCard.title
7 | }}
8 |
9 |
10 |
11 |
12 |
13 |
38 |
--------------------------------------------------------------------------------
/web_frontend/plugins/README.md:
--------------------------------------------------------------------------------
1 | # PLUGINS
2 |
3 | **This directory is not required, you can delete it if you don't want to use it.**
4 |
5 | This directory contains Javascript plugins that you want to run before mounting the root Vue.js application.
6 |
7 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/plugins).
8 |
--------------------------------------------------------------------------------
/web_frontend/plugins/apollo-error-handler.js:
--------------------------------------------------------------------------------
1 | export default (error, nuxtContext) => {
2 | console.log(error)
3 | }
4 |
--------------------------------------------------------------------------------
/web_frontend/plugins/apollo-watch-loading-handler.js:
--------------------------------------------------------------------------------
1 | let loading
2 | export default (isLoading, countModifier, nuxtContext) => {
3 | loading += countModifier
4 | console.log(loading)
5 | }
6 |
--------------------------------------------------------------------------------
/web_frontend/plugins/default-apollo-config.js:
--------------------------------------------------------------------------------
1 | export default function(context) {
2 | let url = ''
3 | const isServer = process.server
4 |
5 | if (isServer) {
6 | url = 'http://cms:8000/'
7 | } else {
8 | url = 'http://localhost:8000/'
9 | }
10 |
11 | url = url + 'api/graphiql'
12 | return {
13 | httpEndpoint: url
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/web_frontend/plugins/v-body-scroll-lock.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import VBodyScrollLock from 'v-body-scroll-lock'
3 |
4 | Vue.use(VBodyScrollLock)
5 |
--------------------------------------------------------------------------------
/web_frontend/static/favicon/android-icon-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devs-group/wagtail-nuxt/21966fe77c7b07750c7f0c09cb65fff77d2f05ce/web_frontend/static/favicon/android-icon-144x144.png
--------------------------------------------------------------------------------
/web_frontend/static/favicon/android-icon-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devs-group/wagtail-nuxt/21966fe77c7b07750c7f0c09cb65fff77d2f05ce/web_frontend/static/favicon/android-icon-192x192.png
--------------------------------------------------------------------------------
/web_frontend/static/favicon/android-icon-36x36.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devs-group/wagtail-nuxt/21966fe77c7b07750c7f0c09cb65fff77d2f05ce/web_frontend/static/favicon/android-icon-36x36.png
--------------------------------------------------------------------------------
/web_frontend/static/favicon/android-icon-48x48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devs-group/wagtail-nuxt/21966fe77c7b07750c7f0c09cb65fff77d2f05ce/web_frontend/static/favicon/android-icon-48x48.png
--------------------------------------------------------------------------------
/web_frontend/static/favicon/android-icon-72x72.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devs-group/wagtail-nuxt/21966fe77c7b07750c7f0c09cb65fff77d2f05ce/web_frontend/static/favicon/android-icon-72x72.png
--------------------------------------------------------------------------------
/web_frontend/static/favicon/android-icon-96x96.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devs-group/wagtail-nuxt/21966fe77c7b07750c7f0c09cb65fff77d2f05ce/web_frontend/static/favicon/android-icon-96x96.png
--------------------------------------------------------------------------------
/web_frontend/static/favicon/apple-icon-114x114.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devs-group/wagtail-nuxt/21966fe77c7b07750c7f0c09cb65fff77d2f05ce/web_frontend/static/favicon/apple-icon-114x114.png
--------------------------------------------------------------------------------
/web_frontend/static/favicon/apple-icon-120x120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devs-group/wagtail-nuxt/21966fe77c7b07750c7f0c09cb65fff77d2f05ce/web_frontend/static/favicon/apple-icon-120x120.png
--------------------------------------------------------------------------------
/web_frontend/static/favicon/apple-icon-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devs-group/wagtail-nuxt/21966fe77c7b07750c7f0c09cb65fff77d2f05ce/web_frontend/static/favicon/apple-icon-144x144.png
--------------------------------------------------------------------------------
/web_frontend/static/favicon/apple-icon-152x152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devs-group/wagtail-nuxt/21966fe77c7b07750c7f0c09cb65fff77d2f05ce/web_frontend/static/favicon/apple-icon-152x152.png
--------------------------------------------------------------------------------
/web_frontend/static/favicon/apple-icon-180x180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devs-group/wagtail-nuxt/21966fe77c7b07750c7f0c09cb65fff77d2f05ce/web_frontend/static/favicon/apple-icon-180x180.png
--------------------------------------------------------------------------------
/web_frontend/static/favicon/apple-icon-57x57.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devs-group/wagtail-nuxt/21966fe77c7b07750c7f0c09cb65fff77d2f05ce/web_frontend/static/favicon/apple-icon-57x57.png
--------------------------------------------------------------------------------
/web_frontend/static/favicon/apple-icon-60x60.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devs-group/wagtail-nuxt/21966fe77c7b07750c7f0c09cb65fff77d2f05ce/web_frontend/static/favicon/apple-icon-60x60.png
--------------------------------------------------------------------------------
/web_frontend/static/favicon/apple-icon-72x72.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devs-group/wagtail-nuxt/21966fe77c7b07750c7f0c09cb65fff77d2f05ce/web_frontend/static/favicon/apple-icon-72x72.png
--------------------------------------------------------------------------------
/web_frontend/static/favicon/apple-icon-76x76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devs-group/wagtail-nuxt/21966fe77c7b07750c7f0c09cb65fff77d2f05ce/web_frontend/static/favicon/apple-icon-76x76.png
--------------------------------------------------------------------------------
/web_frontend/static/favicon/apple-icon-precomposed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devs-group/wagtail-nuxt/21966fe77c7b07750c7f0c09cb65fff77d2f05ce/web_frontend/static/favicon/apple-icon-precomposed.png
--------------------------------------------------------------------------------
/web_frontend/static/favicon/apple-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devs-group/wagtail-nuxt/21966fe77c7b07750c7f0c09cb65fff77d2f05ce/web_frontend/static/favicon/apple-icon.png
--------------------------------------------------------------------------------
/web_frontend/static/favicon/browserconfig.xml:
--------------------------------------------------------------------------------
1 |
2 | #ffffff
--------------------------------------------------------------------------------
/web_frontend/static/favicon/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devs-group/wagtail-nuxt/21966fe77c7b07750c7f0c09cb65fff77d2f05ce/web_frontend/static/favicon/favicon-16x16.png
--------------------------------------------------------------------------------
/web_frontend/static/favicon/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devs-group/wagtail-nuxt/21966fe77c7b07750c7f0c09cb65fff77d2f05ce/web_frontend/static/favicon/favicon-32x32.png
--------------------------------------------------------------------------------
/web_frontend/static/favicon/favicon-96x96.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devs-group/wagtail-nuxt/21966fe77c7b07750c7f0c09cb65fff77d2f05ce/web_frontend/static/favicon/favicon-96x96.png
--------------------------------------------------------------------------------
/web_frontend/static/favicon/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devs-group/wagtail-nuxt/21966fe77c7b07750c7f0c09cb65fff77d2f05ce/web_frontend/static/favicon/favicon.ico
--------------------------------------------------------------------------------
/web_frontend/static/favicon/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "App",
3 | "icons": [
4 | {
5 | "src": "\/android-icon-36x36.png",
6 | "sizes": "36x36",
7 | "type": "image\/png",
8 | "density": "0.75"
9 | },
10 | {
11 | "src": "\/android-icon-48x48.png",
12 | "sizes": "48x48",
13 | "type": "image\/png",
14 | "density": "1.0"
15 | },
16 | {
17 | "src": "\/android-icon-72x72.png",
18 | "sizes": "72x72",
19 | "type": "image\/png",
20 | "density": "1.5"
21 | },
22 | {
23 | "src": "\/android-icon-96x96.png",
24 | "sizes": "96x96",
25 | "type": "image\/png",
26 | "density": "2.0"
27 | },
28 | {
29 | "src": "\/android-icon-144x144.png",
30 | "sizes": "144x144",
31 | "type": "image\/png",
32 | "density": "3.0"
33 | },
34 | {
35 | "src": "\/android-icon-192x192.png",
36 | "sizes": "192x192",
37 | "type": "image\/png",
38 | "density": "4.0"
39 | }
40 | ]
41 | }
--------------------------------------------------------------------------------
/web_frontend/static/favicon/ms-icon-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devs-group/wagtail-nuxt/21966fe77c7b07750c7f0c09cb65fff77d2f05ce/web_frontend/static/favicon/ms-icon-144x144.png
--------------------------------------------------------------------------------
/web_frontend/static/favicon/ms-icon-150x150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devs-group/wagtail-nuxt/21966fe77c7b07750c7f0c09cb65fff77d2f05ce/web_frontend/static/favicon/ms-icon-150x150.png
--------------------------------------------------------------------------------
/web_frontend/static/favicon/ms-icon-310x310.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devs-group/wagtail-nuxt/21966fe77c7b07750c7f0c09cb65fff77d2f05ce/web_frontend/static/favicon/ms-icon-310x310.png
--------------------------------------------------------------------------------
/web_frontend/static/favicon/ms-icon-70x70.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devs-group/wagtail-nuxt/21966fe77c7b07750c7f0c09cb65fff77d2f05ce/web_frontend/static/favicon/ms-icon-70x70.png
--------------------------------------------------------------------------------
/web_frontend/tailwind.config.js:
--------------------------------------------------------------------------------
1 | /*
2 | ** TailwindCSS Configuration File
3 | **
4 | ** Docs: https://tailwindcss.com/docs/configuration
5 | ** Default: https://github.com/tailwindcss/tailwindcss/blob/master/stubs/defaultConfig.stub.js
6 | */
7 | module.exports = {
8 | theme: {
9 | fontFamily: {
10 | monotalic: 'monotalic, sans-serif',
11 | moret: 'moret, serif',
12 | signo: 'signo sans-serif'
13 | },
14 | extend: {
15 | colors: {
16 | 'custom-brown': '#886562',
17 | 'custom-gold': '#877646',
18 | 'custom-green': '#234F40',
19 | 'custom-green-bright': '#828536',
20 | 'custom-green-brightest': '#818564',
21 | 'custom-turquoise': '#20696b'
22 | },
23 | letterSpacing: {
24 | '7-5': '7.5px'
25 | },
26 | fontSize: {
27 | xxxs: '0.625rem',
28 | xxs: '0.6875rem',
29 | '1xl': '1.375rem',
30 | '5xl': '3.5rem'
31 | },
32 | opacity: {
33 | '35': '.35'
34 | },
35 | height: {
36 | '38': '9.5rem'
37 | },
38 | spacing: {
39 | 14: '3.5rem'
40 | },
41 | maxWidth: {
42 | half: '50%'
43 | }
44 | }
45 | },
46 | variants: {},
47 | plugins: []
48 | }
49 |
--------------------------------------------------------------------------------