Update scripts for building and deployment
This commit is contained in:
parent
a431f35743
commit
424af03ce1
|
|
@ -283,3 +283,5 @@ cypress/screenshots
|
||||||
cypress/test-reports
|
cypress/test-reports
|
||||||
|
|
||||||
/server/vbv_lernwelt/static/css/tailwind.css
|
/server/vbv_lernwelt/static/css/tailwind.css
|
||||||
|
/server/vbv_lernwelt/static/vue/
|
||||||
|
/server/vbv_lernwelt/templates/vue/index.html
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ cap.deploy_one_click_app(
|
||||||
namespace='vbv-lernwelt',
|
namespace='vbv-lernwelt',
|
||||||
# check https://github.com/caprover/one-click-apps/blob/master/public/v4/apps/postgres.yml
|
# check https://github.com/caprover/one-click-apps/blob/master/public/v4/apps/postgres.yml
|
||||||
app_variables={
|
app_variables={
|
||||||
'$$cap_postgres_version': '14.1',
|
'$$cap_postgres_version': '14.2',
|
||||||
'$$cap_pg_user': db_user,
|
'$$cap_pg_user': db_user,
|
||||||
'$$cap_pg_pass': db_pass,
|
'$$cap_pg_pass': db_pass,
|
||||||
'$$cap_pg_db': db_name,
|
'$$cap_pg_db': db_name,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
# create client
|
||||||
|
npm run build
|
||||||
|
|
||||||
# create and push new docker container
|
# create and push new docker container
|
||||||
docker build -f compose/django/Dockerfile -t iterativ/vbv-lernwelt-django .
|
docker build -f compose/django/Dockerfile -t iterativ/vbv-lernwelt-django .
|
||||||
docker push iterativ/vbv-lernwelt-django
|
docker push iterativ/vbv-lernwelt-django
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "vue-tsc --noEmit && vite build",
|
"build": "vue-tsc --noEmit && vite build && cp ./dist/index.html ../server/vbv_lernwelt/templates/vue/index.html && cp -r ./dist/static/vue ../server/vbv_lernwelt/static/",
|
||||||
"preview": "vite preview --port 5050",
|
"preview": "vite preview --port 5050",
|
||||||
"test:unit": "vitest --environment jsdom",
|
"test:unit": "vitest --environment jsdom",
|
||||||
"test:e2e": "start-server-and-test preview http://127.0.0.1:5050/ 'cypress open'",
|
"test:e2e": "start-server-and-test preview http://127.0.0.1:5050/ 'cypress open'",
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { createApp } from 'vue'
|
import {createApp} from 'vue'
|
||||||
import { createPinia } from 'pinia'
|
import {createPinia} from 'pinia'
|
||||||
|
|
||||||
import {setupI18n, loadLocaleMessages} from './i18n'
|
import {setupI18n} from './i18n'
|
||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
import router from './router'
|
import router from './router'
|
||||||
|
|
||||||
|
|
@ -11,7 +11,7 @@ const i18n = setupI18n()
|
||||||
const app = createApp(App)
|
const app = createApp(App)
|
||||||
|
|
||||||
// todo: define lang setup
|
// todo: define lang setup
|
||||||
await loadLocaleMessages(i18n, 'de')
|
// await loadLocaleMessages(i18n, 'de')
|
||||||
|
|
||||||
app.use(createPinia())
|
app.use(createPinia())
|
||||||
app.use(router)
|
app.use(router)
|
||||||
|
|
|
||||||
|
|
@ -36,8 +36,8 @@ const router = createRouter({
|
||||||
component: () => import('../views/ProfileView.vue'),
|
component: () => import('../views/ProfileView.vue'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/learningpath/:learningPathId',
|
path: '/:pathMatch(.*)*',
|
||||||
component: () => import('../views/LearningPathOverview.vue'),
|
component: () => import('../views/404View.vue'),
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
<template>
|
||||||
|
<main>
|
||||||
|
<h1>404 - Not Found as Vue view...</h1>
|
||||||
|
</main>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
</style>
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
<template>
|
|
||||||
<h1>Lernpfad Overview</h1>
|
|
||||||
<LearningPath />
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import LearningPath from "../components/LearningPath.vue";
|
|
||||||
export default {
|
|
||||||
name: 'LearningPathOverview',
|
|
||||||
components: {LearningPath}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
import path from 'path'
|
|
||||||
import {fileURLToPath, URL} from 'url'
|
import {fileURLToPath, URL} from 'url'
|
||||||
|
|
||||||
import {defineConfig, loadEnv} from 'vite'
|
import {defineConfig, loadEnv} from 'vite'
|
||||||
import vue from '@vitejs/plugin-vue'
|
import vue from '@vitejs/plugin-vue'
|
||||||
import vueI18n from '@intlify/vite-plugin-vue-i18n'
|
// import vueI18n from '@intlify/vite-plugin-vue-i18n'
|
||||||
import alias from '@rollup/plugin-alias'
|
import alias from '@rollup/plugin-alias'
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
|
|
@ -12,17 +11,18 @@ export default ({mode}) => {
|
||||||
return defineConfig({
|
return defineConfig({
|
||||||
plugins: [
|
plugins: [
|
||||||
vue(),
|
vue(),
|
||||||
vueI18n({
|
// vueI18n({
|
||||||
include: path.resolve(__dirname, './locales/**')
|
// include: path.resolve(__dirname, './locales/**')
|
||||||
}),
|
// }),
|
||||||
// won't work in vite's resolve.alias, so we'll make the alias here
|
// won't work in vite's resolve.alias, so we'll make the alias here
|
||||||
alias({
|
alias({
|
||||||
entries: [
|
// TODO: why is that used?
|
||||||
{
|
// entries: [
|
||||||
find: 'vue-i18n',
|
// {
|
||||||
replacement: path.resolve(__dirname, './node_modules/vue-i18n/dist/vue-i18n.runtime.esm-bundler.js')
|
// find: 'vue-i18n',
|
||||||
}
|
// replacement: path.resolve(__dirname, './node_modules/vue-i18n/dist/vue-i18n.runtime.esm-bundler.js')
|
||||||
]
|
// }
|
||||||
|
// ]
|
||||||
})
|
})
|
||||||
],
|
],
|
||||||
resolve: {
|
resolve: {
|
||||||
|
|
@ -30,5 +30,8 @@ export default ({mode}) => {
|
||||||
'@': fileURLToPath(new URL('./src', import.meta.url)),
|
'@': fileURLToPath(new URL('./src', import.meta.url)),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
build: {
|
||||||
|
assetsDir: 'static/vue',
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,7 @@ FROM node:16-bullseye-slim as client-builder
|
||||||
ARG APP_HOME=/app
|
ARG APP_HOME=/app
|
||||||
WORKDIR ${APP_HOME}
|
WORKDIR ${APP_HOME}
|
||||||
|
|
||||||
COPY ./server/package.json ${APP_HOME}
|
|
||||||
RUN npm install && npm cache clean --force
|
|
||||||
COPY ./server ${APP_HOME}
|
COPY ./server ${APP_HOME}
|
||||||
RUN npm run build
|
|
||||||
|
|
||||||
# define an alias for the specfic python version used in this file.
|
# define an alias for the specfic python version used in this file.
|
||||||
FROM python:${PYTHON_VERSION} as python
|
FROM python:${PYTHON_VERSION} as python
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,8 @@ set -o errexit
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
set -o nounset
|
set -o nounset
|
||||||
|
|
||||||
|
|
||||||
python /app/manage.py collectstatic --noinput
|
python /app/manage.py collectstatic --noinput
|
||||||
python /app/manage.py migrate
|
|
||||||
python /app/manage.py createcachetable
|
python /app/manage.py createcachetable
|
||||||
|
python /app/manage.py migrate
|
||||||
|
|
||||||
/usr/local/bin/gunicorn config.asgi --bind 0.0.0.0:80 --chdir=/app -k uvicorn.workers.UvicornWorker
|
/usr/local/bin/gunicorn config.asgi --bind 0.0.0.0:80 --chdir=/app -k uvicorn.workers.UvicornWorker
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
"name": "vbv_lernwelt_cypress",
|
"name": "vbv_lernwelt_cypress",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"build": "npm install --prefix client && npm run build --prefix client && npm run build:tailwind",
|
||||||
|
"build:tailwind": "tailwindcss -i ./tailwind/input.css -o ./server/vbv_lernwelt/static/css/tailwind.css --minify",
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
"cypress:open": "cypress open",
|
"cypress:open": "cypress open",
|
||||||
"cypress:run": "cypress run",
|
"cypress:run": "cypress run",
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ if [ "$SKIP_SETUP" = false ]; then
|
||||||
python3 server/manage.py createcachetable --settings="$DJANGO_SETTINGS_MODULE"
|
python3 server/manage.py createcachetable --settings="$DJANGO_SETTINGS_MODULE"
|
||||||
python3 server/manage.py migrate --settings="$DJANGO_SETTINGS_MODULE"
|
python3 server/manage.py migrate --settings="$DJANGO_SETTINGS_MODULE"
|
||||||
python3 server/manage.py create_default_users --settings="$DJANGO_SETTINGS_MODULE"
|
python3 server/manage.py create_default_users --settings="$DJANGO_SETTINGS_MODULE"
|
||||||
python3 server/manage.py create_default_learningpath --settings="$DJANGO_SETTINGS_MODULE"
|
python3 server/manage.py create_default_learning_path --settings="$DJANGO_SETTINGS_MODULE"
|
||||||
|
|
||||||
# make django translations
|
# make django translations
|
||||||
(cd server && python3 manage.py compilemessages --settings="$DJANGO_SETTINGS_MODULE")
|
(cd server && python3 manage.py compilemessages --settings="$DJANGO_SETTINGS_MODULE")
|
||||||
|
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
||||||
version: '3'
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
production_postgres_data: {}
|
|
||||||
production_postgres_data_backups: {}
|
|
||||||
production_traefik: {}
|
|
||||||
|
|
||||||
services:
|
|
||||||
django:
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
dockerfile: ./compose/production/django/Dockerfile
|
|
||||||
image: vbv_lernwelt_production_django
|
|
||||||
depends_on:
|
|
||||||
- postgres
|
|
||||||
- redis
|
|
||||||
env_file:
|
|
||||||
- env_secrets/production.env
|
|
||||||
command: /start
|
|
||||||
|
|
||||||
postgres:
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
dockerfile: ./compose/production/postgres/Dockerfile
|
|
||||||
image: vbv_lernwelt_production_postgres
|
|
||||||
volumes:
|
|
||||||
- production_postgres_data:/var/lib/postgresql/data:Z
|
|
||||||
- production_postgres_data_backups:/backups:z
|
|
||||||
env_file:
|
|
||||||
- env_secrets/production.env
|
|
||||||
|
|
||||||
traefik:
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
dockerfile: ./compose/production/traefik/Dockerfile
|
|
||||||
image: vbv_lernwelt_production_traefik
|
|
||||||
depends_on:
|
|
||||||
- django
|
|
||||||
volumes:
|
|
||||||
- production_traefik:/etc/traefik/acme:z
|
|
||||||
ports:
|
|
||||||
- "0.0.0.0:80:80"
|
|
||||||
- "0.0.0.0:443:443"
|
|
||||||
|
|
||||||
redis:
|
|
||||||
image: redis:6
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.conf.urls.static import static
|
from django.conf.urls.static import static
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
|
@ -19,7 +18,7 @@ from vbv_lernwelt.core.middleware.auth import django_view_authentication_exempt
|
||||||
from vbv_lernwelt.core.views import (
|
from vbv_lernwelt.core.views import (
|
||||||
rate_limit_exceeded_view,
|
rate_limit_exceeded_view,
|
||||||
permission_denied_view,
|
permission_denied_view,
|
||||||
check_rate_limit, vue_home,
|
check_rate_limit, vue_home, cypress_reset_view,
|
||||||
)
|
)
|
||||||
from .wagtail_api import api_router
|
from .wagtail_api import api_router
|
||||||
|
|
||||||
|
|
@ -65,6 +64,11 @@ urlpatterns += [
|
||||||
path("api/docs/", SpectacularSwaggerView.as_view(url_name="api-schema"), name="api-docs",),
|
path("api/docs/", SpectacularSwaggerView.as_view(url_name="api-schema"), name="api-docs",),
|
||||||
path("", include(grapple_urls)),
|
path("", include(grapple_urls)),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
if settings.APP_ENVIRONMENT != 'production':
|
||||||
|
urlpatterns += [
|
||||||
|
re_path(r'cypressreset/$', cypress_reset_view, name='cypress_reset_view'),
|
||||||
|
]
|
||||||
# fmt: on
|
# fmt: on
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
python manage.py migrate
|
|
||||||
python manage.py createcachetable
|
|
||||||
python manage.py create_default_users
|
|
||||||
#python manage.py create_default_learingpath
|
|
||||||
|
|
||||||
|
|
@ -4,17 +4,24 @@ from django.contrib.auth.models import Group
|
||||||
from vbv_lernwelt.core.models import User
|
from vbv_lernwelt.core.models import User
|
||||||
|
|
||||||
|
|
||||||
def create_default_users(user_model=User, group_model=Group):
|
def create_default_users(user_model=User, group_model=Group, default_password=None):
|
||||||
admin_group, created = group_model.objects.get_or_create(name='admin_group')
|
admin_group, created = group_model.objects.get_or_create(name='admin_group')
|
||||||
content_creator_grop, created = group_model.objects.get_or_create(name='content_creator_grop')
|
content_creator_grop, created = group_model.objects.get_or_create(name='content_creator_grop')
|
||||||
student_group, created = group_model.objects.get_or_create(name='student_group')
|
student_group, created = group_model.objects.get_or_create(name='student_group')
|
||||||
|
|
||||||
admin_user, created = _get_or_create_user(user_model=user_model, username='admin', password='admin')
|
admin_password = default_password
|
||||||
|
if not admin_password:
|
||||||
|
admin_password = 'admin'
|
||||||
|
admin_user, created = _get_or_create_user(user_model=user_model, username='admin', password=admin_password)
|
||||||
admin_user.is_superuser = True
|
admin_user.is_superuser = True
|
||||||
|
admin_user.is_staff = True
|
||||||
admin_user.groups.add(admin_group)
|
admin_user.groups.add(admin_group)
|
||||||
admin_user.save()
|
admin_user.save()
|
||||||
|
|
||||||
student_user, created = _get_or_create_user(user_model=user_model, username='student', password='student')
|
student_user_password = default_password
|
||||||
|
if not student_user_password:
|
||||||
|
student_user_password = 'student'
|
||||||
|
student_user, created = _get_or_create_user(user_model=user_model, username='student', password=student_user_password)
|
||||||
student_user.groups.add(student_group)
|
student_user.groups.add(student_group)
|
||||||
student_user.save()
|
student_user.save()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
from vbv_lernwelt.core.create_default_users import create_default_users
|
|
||||||
|
|
||||||
|
|
||||||
import djclick as click
|
import djclick as click
|
||||||
|
|
||||||
|
from vbv_lernwelt.core.create_default_users import create_default_users
|
||||||
|
|
||||||
|
|
||||||
@click.command()
|
@click.command()
|
||||||
def command():
|
def command():
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
# pylint: disable=import-outside-toplevel
|
|
||||||
|
|
||||||
import djclick as click
|
import djclick as click
|
||||||
from django.contrib.auth import get_user_model
|
|
||||||
|
from vbv_lernwelt.learnpath.tests.create_default_learning_path import create_default_learning_path, \
|
||||||
|
delete_default_learning_path
|
||||||
|
|
||||||
|
|
||||||
@click.command()
|
@click.command()
|
||||||
|
|
@ -9,17 +9,5 @@ from django.contrib.auth import get_user_model
|
||||||
def command(customer_language):
|
def command(customer_language):
|
||||||
print("cypress reset data")
|
print("cypress reset data")
|
||||||
|
|
||||||
User = get_user_model()
|
delete_default_learning_path()
|
||||||
|
create_default_learning_path()
|
||||||
users = [
|
|
||||||
"cypress@example.com",
|
|
||||||
]
|
|
||||||
for user in users:
|
|
||||||
User.objects.filter(username=user).delete()
|
|
||||||
|
|
||||||
user = User.objects.create(
|
|
||||||
username=user,
|
|
||||||
email=user,
|
|
||||||
)
|
|
||||||
user.set_password("test")
|
|
||||||
user.save()
|
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,16 @@
|
||||||
|
from django.conf import settings
|
||||||
|
from django.contrib.auth.models import Group
|
||||||
from django.db import migrations
|
from django.db import migrations
|
||||||
|
|
||||||
|
from vbv_lernwelt.core.create_default_users import create_default_users
|
||||||
from vbv_lernwelt.core.models import User
|
from vbv_lernwelt.core.models import User
|
||||||
|
|
||||||
|
|
||||||
def create_iterativ_users(apps, schema_editor):
|
def create_users(apps, schema_editor):
|
||||||
for username in [
|
default_password = 'ACEEs0DCmNaPxdoNV8vhccuCTRl9b'
|
||||||
"info@iterativ.ch",
|
if settings.APP_ENVIRONMENT == 'development':
|
||||||
]:
|
default_password = None
|
||||||
user = User.objects.create(
|
create_default_users(user_model=User, group_model=Group, default_password=default_password)
|
||||||
username=username,
|
|
||||||
email=username,
|
|
||||||
is_superuser=True,
|
|
||||||
is_staff=True,
|
|
||||||
)
|
|
||||||
user.set_password("ACEEs0DCmNaPxdoNV8vhccuCTRl9b")
|
|
||||||
user.save()
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
@ -23,5 +19,5 @@ class Migration(migrations.Migration):
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
migrations.RunPython(create_iterativ_users),
|
migrations.RunPython(create_users),
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,14 @@
|
||||||
# Create your views here.
|
# Create your views here.
|
||||||
import requests
|
import requests
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.http import JsonResponse, HttpResponse
|
from django.core.management import call_command
|
||||||
|
from django.http import JsonResponse, HttpResponse, HttpResponseRedirect
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
from django.views.decorators.csrf import ensure_csrf_cookie
|
from django.views.decorators.csrf import ensure_csrf_cookie
|
||||||
from ratelimit.decorators import ratelimit
|
from ratelimit.decorators import ratelimit
|
||||||
|
from rest_framework import authentication
|
||||||
|
from rest_framework.decorators import api_view, authentication_classes, permission_classes
|
||||||
|
from rest_framework.permissions import IsAdminUser
|
||||||
|
|
||||||
from vbv_lernwelt.core.middleware.auth import django_view_authentication_exempt
|
from vbv_lernwelt.core.middleware.auth import django_view_authentication_exempt
|
||||||
|
|
||||||
|
|
@ -24,7 +28,7 @@ def vue_home(request):
|
||||||
)
|
)
|
||||||
|
|
||||||
# render index.html from `npm run build`
|
# render index.html from `npm run build`
|
||||||
return render(request, 'index.html', {})
|
return render(request, 'vue/index.html', {})
|
||||||
|
|
||||||
|
|
||||||
def permission_denied_view(request, exception):
|
def permission_denied_view(request, exception):
|
||||||
|
|
@ -51,3 +55,13 @@ def server_json_error(request, *args, **kwargs):
|
||||||
@django_view_authentication_exempt
|
@django_view_authentication_exempt
|
||||||
def check_rate_limit(request):
|
def check_rate_limit(request):
|
||||||
return HttpResponse(content=b"Hello")
|
return HttpResponse(content=b"Hello")
|
||||||
|
|
||||||
|
|
||||||
|
@api_view(['POST'])
|
||||||
|
@authentication_classes((authentication.SessionAuthentication,))
|
||||||
|
@permission_classes((IsAdminUser,))
|
||||||
|
def cypress_reset_view(request):
|
||||||
|
if settings.APP_ENVIRONMENT != 'production':
|
||||||
|
call_command('cypress_reset')
|
||||||
|
|
||||||
|
return HttpResponseRedirect('/admin/')
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
# pylint: disable=import-outside-toplevel
|
|
||||||
|
|
||||||
import djclick as click
|
import djclick as click
|
||||||
|
|
||||||
from vbv_lernwelt.learnpath.tests.create_default_learning_path import create_default_learning_path
|
from vbv_lernwelt.learnpath.tests.create_default_learning_path import create_default_learning_path
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
import djclick as click
|
||||||
|
|
||||||
|
from vbv_lernwelt.learnpath.tests.create_default_learning_path import delete_default_learning_path
|
||||||
|
|
||||||
|
|
||||||
|
@click.command()
|
||||||
|
def command():
|
||||||
|
delete_default_learning_path()
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
# pylint: disable=import-outside-toplevel
|
|
||||||
|
|
||||||
import djclick as click
|
|
||||||
from django.contrib.auth import get_user_model
|
|
||||||
|
|
||||||
from vbv_lernwelt.learnpath.tests.create_default_learning_path import create_default_learning_path, \
|
|
||||||
delete_default_learning_path
|
|
||||||
|
|
||||||
import djclick as click
|
|
||||||
|
|
||||||
|
|
||||||
@click.command()
|
|
||||||
def command():
|
|
||||||
delete_default_learning_path()
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# Generated by Django 3.2.12 on 2022-05-04 15:52
|
# Generated by Django 3.2.12 on 2022-05-30 13:51
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
|
|
@ -51,6 +51,18 @@ class Migration(migrations.Migration):
|
||||||
},
|
},
|
||||||
bases=('wagtailcore.page',),
|
bases=('wagtailcore.page',),
|
||||||
),
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='LearningPackage',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('sort_order', models.IntegerField(blank=True, editable=False, null=True)),
|
||||||
|
('title', models.CharField(default='', max_length=256)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'ordering': ['sort_order'],
|
||||||
|
'abstract': False,
|
||||||
|
},
|
||||||
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='LearningPath',
|
name='LearningPath',
|
||||||
fields=[
|
fields=[
|
||||||
|
|
@ -61,19 +73,6 @@ class Migration(migrations.Migration):
|
||||||
},
|
},
|
||||||
bases=('wagtailcore.page',),
|
bases=('wagtailcore.page',),
|
||||||
),
|
),
|
||||||
migrations.CreateModel(
|
|
||||||
name='LearningSequence',
|
|
||||||
fields=[
|
|
||||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
||||||
('sort_order', models.IntegerField(blank=True, editable=False, null=True)),
|
|
||||||
('title', models.CharField(default='', max_length=256)),
|
|
||||||
('category', models.CharField(choices=[('INCIRCLE', 'In Circle'), ('START', 'Start'), ('END', 'End')], default='INCIRCLE', max_length=16)),
|
|
||||||
('circle', modelcluster.fields.ParentalKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='learning_sequences', to='learnpath.circle')),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
'verbose_name': 'Learning Sequence',
|
|
||||||
},
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='Topic',
|
name='Topic',
|
||||||
fields=[
|
fields=[
|
||||||
|
|
@ -93,17 +92,36 @@ class Migration(migrations.Migration):
|
||||||
('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')),
|
('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')),
|
||||||
('sort_order', models.IntegerField(blank=True, editable=False, null=True)),
|
('sort_order', models.IntegerField(blank=True, editable=False, null=True)),
|
||||||
('contents', wagtail.core.fields.StreamField([('web_based_training', wagtail.core.blocks.StructBlock([('url', wagtail.core.blocks.URLBlock())])), ('video', wagtail.core.blocks.StructBlock([('url', wagtail.core.blocks.URLBlock())]))], blank=True, null=True)),
|
('contents', wagtail.core.fields.StreamField([('web_based_training', wagtail.core.blocks.StructBlock([('url', wagtail.core.blocks.URLBlock())])), ('video', wagtail.core.blocks.StructBlock([('url', wagtail.core.blocks.URLBlock())]))], blank=True, null=True)),
|
||||||
('learning_sequence', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='learning_units', to='learnpath.learningsequence')),
|
('learning_package', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='learning_units', to='learnpath.learningpackage')),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
'verbose_name': 'Learning Unit',
|
'verbose_name': 'Learning Unit',
|
||||||
},
|
},
|
||||||
bases=('wagtailcore.page', models.Model),
|
bases=('wagtailcore.page', models.Model),
|
||||||
),
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='LearningSequence',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('sort_order', models.IntegerField(blank=True, editable=False, null=True)),
|
||||||
|
('title', models.CharField(default='', max_length=256)),
|
||||||
|
('category', models.CharField(choices=[('INCIRCLE', 'In Circle'), ('START', 'Start'), ('END', 'End')], default='INCIRCLE', max_length=16)),
|
||||||
|
('circle', modelcluster.fields.ParentalKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='learning_sequences', to='learnpath.circle')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'Learning Sequence',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='learningpackage',
|
||||||
|
name='learning_sequence',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='learning_packages', to='learnpath.learningsequence'),
|
||||||
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='FullfillmentCriteria',
|
name='FullfillmentCriteria',
|
||||||
fields=[
|
fields=[
|
||||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('sort_order', models.IntegerField(blank=True, editable=False, null=True)),
|
||||||
('name', models.CharField(max_length=2048)),
|
('name', models.CharField(max_length=2048)),
|
||||||
('competence', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='learnpath.competence')),
|
('competence', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='learnpath.competence')),
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
# Generated by Django 3.2.12 on 2022-05-04 16:00
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('learnpath', '0001_initial'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='fullfillmentcriteria',
|
|
||||||
name='sort_order',
|
|
||||||
field=models.IntegerField(blank=True, editable=False, null=True),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
# Generated by Django 3.2.12 on 2022-05-12 12:56
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
import django.db.models.deletion
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('learnpath', '0002_fullfillmentcriteria_sort_order'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.RemoveField(
|
|
||||||
model_name='learningunit',
|
|
||||||
name='learning_sequence',
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='LearningPackage',
|
|
||||||
fields=[
|
|
||||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
||||||
('sort_order', models.IntegerField(blank=True, editable=False, null=True)),
|
|
||||||
('title', models.CharField(default='', max_length=256)),
|
|
||||||
('learning_sequence', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='learning_packages', to='learnpath.learningsequence')),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
'ordering': ['sort_order'],
|
|
||||||
'abstract': False,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='learningunit',
|
|
||||||
name='learning_package',
|
|
||||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='learning_units', to='learnpath.learningpackage'),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
# Generated by Django 3.2.12 on 2022-05-12 12:56
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
import django.db.models.deletion
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('learnpath', '0003_auto_20220512_1456'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='learningpackage',
|
|
||||||
name='learning_sequence',
|
|
||||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='learning_packages', to='learnpath.learningsequence'),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
# Generated by Django 3.2.12 on 2022-05-12 12:56
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
import django.db.models.deletion
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('learnpath', '0004_alter_learningpackage_learning_sequence'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='learningunit',
|
|
||||||
name='learning_package',
|
|
||||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='learning_units', to='learnpath.learningpackage'),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
@ -2,7 +2,7 @@ import factory
|
||||||
import wagtail_factories
|
import wagtail_factories
|
||||||
|
|
||||||
from vbv_lernwelt.learnpath.models_competences import Competence, FullfillmentCriteria, CompetencePage
|
from vbv_lernwelt.learnpath.models_competences import Competence, FullfillmentCriteria, CompetencePage
|
||||||
from vbv_lernwelt.learnpath.tests.learningpath_factories import LearningPathFactory
|
from vbv_lernwelt.learnpath.tests.learning_path_factories import LearningPathFactory
|
||||||
|
|
||||||
|
|
||||||
class CompetencePageFactory(wagtail_factories.PageFactory):
|
class CompetencePageFactory(wagtail_factories.PageFactory):
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
import wagtail_factories
|
import wagtail_factories
|
||||||
|
from django.conf import settings
|
||||||
from wagtail.core.models import Site
|
from wagtail.core.models import Site
|
||||||
|
|
||||||
from vbv_lernwelt.learnpath.models import LearningPath, Topic, Circle, LearningSequence, LearningUnit
|
from vbv_lernwelt.learnpath.models import LearningPath, Topic, Circle, LearningSequence, LearningUnit
|
||||||
from vbv_lernwelt.learnpath.tests.learningpath_factories import LearningPathFactory, TopicFactory, CircleFactory, \
|
from vbv_lernwelt.learnpath.tests.learning_path_factories import LearningPathFactory, TopicFactory, CircleFactory, \
|
||||||
LearningSequenceFactory, LearningUnitFactory, VideoBlockFactory, WebBasedTrainingBlockFactory, \
|
LearningSequenceFactory, LearningUnitFactory, VideoBlockFactory, WebBasedTrainingBlockFactory, \
|
||||||
LearningPackageFactory
|
LearningPackageFactory
|
||||||
|
|
||||||
|
|
@ -13,8 +14,9 @@ def create_default_learning_path():
|
||||||
if not site:
|
if not site:
|
||||||
site = wagtail_factories.SiteFactory(is_default_site=True)
|
site = wagtail_factories.SiteFactory(is_default_site=True)
|
||||||
|
|
||||||
site.port = 8000
|
if settings.APP_ENVIRONMENT == 'development':
|
||||||
site.save()
|
site.port = 8000
|
||||||
|
site.save()
|
||||||
|
|
||||||
# create_default_competences()
|
# create_default_competences()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import wagtail_factories
|
|
||||||
import factory
|
import factory
|
||||||
|
import wagtail_factories
|
||||||
|
|
||||||
from vbv_lernwelt.learnpath.models import LearningPath, Topic, Circle, LearningSequence, LearningUnit, LearningPackage
|
from vbv_lernwelt.learnpath.models import LearningPath, Topic, Circle, LearningSequence, LearningUnit, LearningPackage
|
||||||
from vbv_lernwelt.learnpath.models_learning_unit_content import VideoBlock, WebBasedTrainingBlock
|
from vbv_lernwelt.learnpath.models_learning_unit_content import VideoBlock, WebBasedTrainingBlock
|
||||||
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
from django.test import TestCase
|
|
||||||
|
|
||||||
from rest_framework.test import APITestCase
|
from rest_framework.test import APITestCase
|
||||||
|
|
||||||
from vbv_lernwelt.core.admin import User
|
from vbv_lernwelt.core.admin import User
|
||||||
|
|
@ -14,8 +12,8 @@ class TestRetrieveLearingPathContents(APITestCase):
|
||||||
def setUpClass(cls) -> None:
|
def setUpClass(cls) -> None:
|
||||||
super(TestRetrieveLearingPathContents, cls).setUpClass()
|
super(TestRetrieveLearingPathContents, cls).setUpClass()
|
||||||
create_locales_for_wagtail()
|
create_locales_for_wagtail()
|
||||||
create_default_learning_path()
|
|
||||||
create_default_users()
|
create_default_users()
|
||||||
|
create_default_learning_path()
|
||||||
|
|
||||||
def setUp(self) -> None:
|
def setUp(self) -> None:
|
||||||
qs = LearningPath.objects.filter(title="Versicherungsvermittler/in")
|
qs = LearningPath.objects.filter(title="Versicherungsvermittler/in")
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,6 @@
|
||||||
from django.conf import settings
|
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from wagtail.core.models import Locale
|
|
||||||
|
|
||||||
from vbv_lernwelt.learnpath.models import LearningPath
|
|
||||||
from vbv_lernwelt.learnpath.tests.create_default_competences import create_default_competences
|
from vbv_lernwelt.learnpath.tests.create_default_competences import create_default_competences
|
||||||
from vbv_lernwelt.learnpath.tests.create_default_learning_path import create_default_learning_path
|
|
||||||
|
|
||||||
|
|
||||||
class TestCreateDefaultCompetences(TestCase):
|
class TestCreateDefaultCompetences(TestCase):
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
{% extends "admin/index.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div id="content-main">
|
||||||
|
{% include "admin/app_list.html" with app_list=app_list show_changelinks=True %}
|
||||||
|
|
||||||
|
<div class="content">
|
||||||
|
<form action="/cypressreset/" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
<button class="" name="">Testdaten zurück setzen</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
@ -8,29 +8,22 @@
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta name="description" content="VBV Lernumgebung">
|
<meta name="description" content="VBV Lernumgebung">
|
||||||
<meta name="author" content="Iterativ GmbH">
|
<meta name="author" content="Iterativ GmbH">
|
||||||
|
|
||||||
<link href="/static/css/tailwind.css" rel="stylesheet">
|
|
||||||
<link rel="icon" href="{% static 'images/favicons/favicon.ico' %}">
|
<link rel="icon" href="{% static 'images/favicons/favicon.ico' %}">
|
||||||
|
|
||||||
{% block css %}
|
{% block css %}
|
||||||
|
<link href="/static/css/tailwind.css" rel="stylesheet">
|
||||||
<!-- Your stuff: Third-party CSS libraries go here -->
|
<!-- Your stuff: Third-party CSS libraries go here -->
|
||||||
<!-- This file stores project-specific CSS -->
|
<!-- This file stores project-specific CSS -->
|
||||||
<link href="{% static 'css/project.min.css' %}" rel="stylesheet">
|
|
||||||
<link href="{% static 'css/output.css' %}" rel="stylesheet">
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
<!-- Le javascript
|
<!-- Le javascript
|
||||||
================================================== -->
|
================================================== -->
|
||||||
{# Placed at the top of the document so pages load faster with defer #}
|
{# Placed at the top of the document so pages load faster with defer #}
|
||||||
<script defer src="https://unpkg.com/htmx.org@1.6.1"></script>
|
<script defer src="https://unpkg.com/htmx.org@1.6.1"></script>
|
||||||
|
|
||||||
|
|
||||||
{% block javascript %}
|
{% block javascript %}
|
||||||
<!-- Your stuff: Third-party javascript libraries go here -->
|
<!-- Your stuff: Third-party javascript libraries go here -->
|
||||||
<!-- place project specific Javascript in this file -->
|
<!-- place project specific Javascript in this file -->
|
||||||
<script defer src="{% static 'js/project.js' %}"></script>
|
|
||||||
<script src="https://d3js.org/d3.v4.min.js"></script>
|
<script src="https://d3js.org/d3.v4.min.js"></script>
|
||||||
|
|
||||||
|
|
||||||
{% endblock javascript %}
|
{% endblock javascript %}
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue