Merged in feature/vbv-132-learning-content-badges-20220921 (pull request #9)

Implement learning content type badges
This commit is contained in:
Elia Bieri 2022-09-27 08:37:46 +00:00
parent 722b9f7937
commit 129507bf6e
24 changed files with 474 additions and 282 deletions

3
.gitignore vendored
View File

@ -258,6 +258,9 @@ GitHub.sublime-settings
[._]s[a-v][a-z] [._]s[a-v][a-z]
[._]sw[a-p] [._]sw[a-p]
#VSCode
.vscode/
# Session # Session
Session.vim Session.vim

View File

@ -0,0 +1,23 @@
<script setup lang="ts">
import type { LearningContentType } from '@/types'
import { learningContentTypesToName } from '@/utils/typeMaps'
const props = defineProps<{
learningContentType: LearningContentType
}>()
</script>
<template>
<div class="flex bg-gray-200 rounded-full px-2.5 py-0.5 gap-2 items-center w-min h-min">
<it-icon-lc-assignment class="w-6 h-6" v-if="props.learningContentType === 'assignment'" />
<it-icon-lc-exercise class="w-6 h-6" v-else-if="props.learningContentType === 'exercise'" />
<it-icon-lc-book class="w-6 h-6" v-else-if="props.learningContentType === 'book'" />
<it-icon-lc-video class="w-6 h-6" v-else-if="props.learningContentType === 'video'" />
<it-icon-lc-media-library class="w-6 h-6" v-else-if="props.learningContentType === 'media_library'" />
<it-icon-lc-test class="w-6 h-6" v-else-if="props.learningContentType === 'test'" />
<it-icon-lc-online-training class="w-6 h-6" v-else-if="props.learningContentType === 'online_training'" />
<it-icon-lc-resource class="w-6 h-6" v-else-if="props.learningContentType === 'resource'" />
<it-icon-lc-document class="w-6 h-6" v-else-if="props.learningContentType === 'document'" />
<p class="whitespace-nowrap">{{ learningContentTypesToName.get(props.learningContentType) }}</p>
</div>
</template>

View File

@ -5,6 +5,7 @@ import { useCircleStore } from '@/stores/circle'
import { computed } from 'vue' import { computed } from 'vue'
import _ from 'lodash' import _ from 'lodash'
import { humanizeDuration } from '@/utils/humanizeDuration' import { humanizeDuration } from '@/utils/humanizeDuration'
import LearningContentBadge from './LearningContentTypeBadge.vue'
const props = defineProps<{ const props = defineProps<{
learningSequence: LearningSequence learningSequence: LearningSequence
@ -52,7 +53,7 @@ const continueTranslationKeyTuple = computed(() => {
}) })
const learningSequenceBorderClass = computed(() => { const learningSequenceBorderClass = computed(() => {
let result = [] let result: string[] = []
if (props.learningSequence && circleStore.circle) { if (props.learningSequence && circleStore.circle) {
if (allFinished.value) { if (allFinished.value) {
result = ['border-l-4', 'border-l-green-500'] result = ['border-l-4', 'border-l-green-500']
@ -81,33 +82,44 @@ const learningSequenceBorderClass = computed(() => {
<div v-for="learningUnit in learningSequence.learningUnits" :key="learningUnit.id" class="pt-3 lg:pt-6"> <div v-for="learningUnit in learningSequence.learningUnits" :key="learningUnit.id" class="pt-3 lg:pt-6">
<div class="pb-3 lg:pg-6 flex gap-4 text-blue-900" v-if="learningUnit.title"> <div class="pb-3 lg:pg-6 flex gap-4 text-blue-900" v-if="learningUnit.title">
<div class="font-semibold">{{ learningUnit.title }}</div> <div class="font-semibold">{{ learningUnit.title }}</div>
<div>{{ humanizeDuration(learningUnit.minutes) }}</div> <div class="whitespace-nowrap">{{ humanizeDuration(learningUnit.minutes) }}</div>
</div> </div>
<div <div
v-for="learningContent in learningUnit.learningContents" v-for="learningContent in learningUnit.learningContents"
:key="learningContent.id" :key="learningContent.id"
class="flex items-center gap-4 pb-3 lg:pb-6" class="flex gap-4 pb-3 lg:pb-6"
> >
<ItCheckbox <ItCheckbox
:modelValue="learningContent.completed" :modelValue="learningContent.completed"
@click="toggleCompleted(learningContent)" :onToggle="() => toggleCompleted(learningContent)"
:data-cy="`${learningContent.slug}`" :data-cy="`${learningContent.slug}`"
> >
<span @click.stop="circleStore.openLearningContent(learningContent)" <span class="flex flex-wrap gap-4 items-center">
>{{ learningContent.contents[0].type }}: {{ learningContent.title }}</span <div
@click.stop="circleStore.openLearningContent(learningContent)"
class="cursor-pointer w-full sm:w-auto"
> >
</ItCheckbox> {{ learningContent.title }}
</div>
<div class="flex items-center gap-4 flex-col justify-between sm:flex-row sm:grow">
<button <button
v-if="learningContent.translation_key === continueTranslationKeyTuple[0]" v-if="learningContent.translation_key === continueTranslationKeyTuple[0]"
class="btn-blue -my-4" class="btn-blue order-1 sm:order-none"
data-cy="ls-continue-button" data-cy="ls-continue-button"
@click.stop="circleStore.openLearningContent(learningContent)" @click.stop="circleStore.openLearningContent(learningContent)"
> >
<span v-if="continueTranslationKeyTuple[1]"> Los geht's </span> <span v-if="continueTranslationKeyTuple[1]" class="whitespace-nowrap">Los geht's </span>
<span v-else> Weiter geht's </span> <span v-else class="whitespace-nowrap"> Weiter geht's </span>
</button> </button>
<div class="hidden sm:block"></div>
<div class="w-full sm:w-auto">
<LearningContentBadge :learningContentType="learningContent.contents[0].type" />
</div>
</div>
</span>
</ItCheckbox>
</div> </div>
<div v-if="learningUnit.id" class="hover:cursor-pointer" @click="circleStore.openSelfEvaluation(learningUnit)"> <div v-if="learningUnit.id" class="hover:cursor-pointer" @click="circleStore.openSelfEvaluation(learningUnit)">

View File

@ -1,7 +1,8 @@
<script setup lang="ts"> <script setup lang="ts">
interface Props { interface Props {
modelValue?: boolean, modelValue?: boolean
disabled?: boolean, disabled?: boolean
onToggle: () => void
} }
const props = withDefaults(defineProps<Props>(), { const props = withDefaults(defineProps<Props>(), {
@ -14,7 +15,7 @@ defineEmits(['update:modelValue'])
<template> <template>
<div <div
class="cursor-pointer flex flex-row items-center" class="flex flex-row sm:place-items-center flex-grow"
:class="{ :class="{
'opacity-50': disabled, 'opacity-50': disabled,
'cursor-not-allowed': disabled, 'cursor-not-allowed': disabled,
@ -23,32 +24,16 @@ defineEmits(['update:modelValue'])
> >
<div <div
v-if="modelValue" v-if="modelValue"
class=" class="w-8 h-8 cursor-pointer flex-none bg-contain bg-[url('/static/icons/icon-checkbox-checked.svg')] hover:bg-[url('/static/icons/icon-checkbox-checked-hover.svg')] disabled:opacity-50 cy-checkbox cy-checkbox-checked"
w-8 h-8 @click.stop="props.onToggle()"
flex-none
bg-contain
bg-[url('/static/icons/icon-checkbox-checked.svg')]
hover:bg-[url('/static/icons/icon-checkbox-checked-hover.svg')]
disabled:opacity-50
cy-checkbox
cy-checkbox-checked
"
></div> ></div>
<div <div
v-else v-else
class=" class="w-8 h-8 cursor-pointer flex-none bg-contain bg-[url('/static/icons/icon-checkbox-unchecked.svg')] hover:bg-[url('/static/icons/icon-checkbox-unchecked-hover.svg')] cy-checkbox cy-checkbox-unchecked"
w-8 h-8 @click.stop="props.onToggle()"
flex-none
bg-contain
bg-[url('/static/icons/icon-checkbox-unchecked.svg')]
hover:bg-[url('/static/icons/icon-checkbox-unchecked-hover.svg')]
cy-checkbox
cy-checkbox-unchecked
"
></div> ></div>
<div class="flex-auto pl-4"> <div class="flex-auto pl-4 pt-1 sm:pt-0">
<slot></slot> <slot></slot>
</div> </div>
</div> </div>
</template> </template>

View File

@ -1,15 +1,19 @@
import type { Circle } from '@/services/circle' import type { Circle } from '@/services/circle'
export type LearningContentType = 'assignment' | 'book' | 'document' |
'exercise' | 'media_library' | 'online_training' |
'resource' | 'test' | 'video';
export interface LearningContentBlock { export interface LearningContentBlock {
type: 'web-based-training' | 'competence' | 'exercise' | 'knowledge' type: LearningContentType
value: { value: {
description: string description: string
} }
id: string id: string
} }
export interface VideoBlock { export interface AssignmentBlock {
type: 'video'; type: 'assignment';
value: { value: {
description: string; description: string;
url: string; url: string;
@ -17,8 +21,8 @@ export interface VideoBlock {
id: string; id: string;
} }
export interface PodcastBlock { export interface BookBlock {
type: 'podcast'; type: 'book';
value: { value: {
description: string; description: string;
url: string; url: string;
@ -35,6 +39,61 @@ export interface DocumentBlock {
id: string; id: string;
} }
export interface ExerciseBlock {
type: 'exercise';
value: {
description: string;
url: string;
},
id: string;
}
export interface MediaLibraryBlock {
type: 'media_library';
value: {
description: string;
url: string;
},
id: string;
}
export interface OnlineTrainingBlock {
type: 'online_training';
value: {
description: string;
url: string;
},
id: string;
}
export interface ResourceBlock {
type: 'resource';
value: {
description: string;
url: string;
},
id: string;
}
export interface TestBlock {
type: 'test';
value: {
description: string;
url: string;
},
id: string;
}
export interface VideoBlock {
type: 'video';
value: {
description: string;
url: string;
},
id: string;
}
export interface CircleGoal { export interface CircleGoal {
type: 'goal'; type: 'goal';
value: string; value: string;
@ -58,7 +117,7 @@ export interface LearningWagtailPage {
export interface LearningContent extends LearningWagtailPage { export interface LearningContent extends LearningWagtailPage {
type: 'learnpath.LearningContent'; type: 'learnpath.LearningContent';
minutes: number; minutes: number;
contents: (LearningContentBlock | VideoBlock | PodcastBlock | DocumentBlock)[]; contents: (AssignmentBlock | BookBlock | DocumentBlock | ExerciseBlock | MediaLibraryBlock | OnlineTrainingBlock | ResourceBlock | TestBlock | VideoBlock)[];
parentCircle: Circle; parentCircle: Circle;
parentLearningSequence?: LearningSequence; parentLearningSequence?: LearningSequence;
parentLearningUnit?: LearningUnit; parentLearningUnit?: LearningUnit;

View File

@ -0,0 +1,13 @@
import type { LearningContentType } from '@/types';
export const learningContentTypesToName = new Map<LearningContentType, string>([
['assignment', 'Auftrag'],
['book', 'Buch'],
['document', 'Dokument'],
['exercise', 'Übung'],
['media_library', 'Mediathek'],
['online_training', 'Online-Training'],
['video', 'Video'],
['test', 'Test'],
['resource', 'Hilfsmittel'],
]);

View File

@ -1,28 +1,26 @@
<script setup lang="ts"> <script setup lang="ts">
import { reactive } from 'vue'
import {reactive} from 'vue' import { Listbox, ListboxButton, ListboxOption, ListboxOptions } from '@headlessui/vue'
import {Listbox, ListboxButton, ListboxOption, ListboxOptions} from '@headlessui/vue' import ItCheckbox from '@/components/ui/ItCheckbox.vue'
import ItCheckbox from '@/components/ui/ItCheckbox.vue'; import ItDropdown from '@/components/ui/ItDropdown.vue'
import ItDropdown from "@/components/ui/ItDropdown.vue"; import IconLogout from '@/components/icons/IconLogout.vue'
import IconLogout from "@/components/icons/IconLogout.vue" import IconSettings from '@/components/icons/IconSettings.vue'
import IconSettings from "@/components/icons/IconSettings.vue"
const state = reactive({ const state = reactive({
checkboxValue: true, checkboxValue: true,
dropdownValues: [ dropdownValues: [
{id: 1, name: 'Wade Cooper'}, { id: 1, name: 'Wade Cooper' },
{id: 2, name: 'Arlene Mccoy'}, { id: 2, name: 'Arlene Mccoy' },
{id: 3, name: 'Devon Webb'}, { id: 3, name: 'Devon Webb' },
{id: 4, name: 'Tom Cook'}, { id: 4, name: 'Tom Cook' },
{id: 5, name: 'Tanya Fox'}, { id: 5, name: 'Tanya Fox' },
{id: 6, name: 'Hellen Schmidt'}, { id: 6, name: 'Hellen Schmidt' },
{id: 7, name: 'Caroline Schultz'}, { id: 7, name: 'Caroline Schultz' },
{id: 8, name: 'Mason Heaney'}, { id: 8, name: 'Mason Heaney' },
{id: 9, name: 'Claudie Smitham'}, { id: 9, name: 'Claudie Smitham' },
{id: 10, name: 'Emil Schaefer'}, { id: 10, name: 'Emil Schaefer' },
], ],
dropdownSelected: {id: 8}, dropdownSelected: { id: 8 },
}) })
const dropdownData = [ const dropdownData = [
@ -30,41 +28,40 @@ const dropdownData = [
{ {
title: 'Option 1', title: 'Option 1',
icon: IconLogout, icon: IconLogout,
data: {} data: {},
}, },
{ {
title: 'Option 2', title: 'Option 2',
icon: null, icon: null,
data: { data: {
test: 12 test: 12,
} },
} },
], ],
[ [
{ {
title: 'Option 3', title: 'Option 3',
icon: IconSettings, icon: IconSettings,
data: { data: {
amount: 34 amount: 34,
}
}, },
] },
] ],
]
// TODO: die CSS-Klasse für die Farben wird hier in der StyleGuideView.vue generiert. // TODO: die CSS-Klasse für die Farben wird hier in der StyleGuideView.vue generiert.
// deshalb muss man diese CSS-Klassen in tailwind.config.js "safelist"en, wenn diese sonst // deshalb muss man diese CSS-Klassen in tailwind.config.js "safelist"en, wenn diese sonst
// noch nirgendwo verwendet werden. // noch nirgendwo verwendet werden.
const colors = ['blue', 'sky', 'green', 'red', 'orange', 'yellow', 'stone', 'gray', 'slate']; const colors = ['blue', 'sky', 'green', 'red', 'orange', 'yellow', 'stone', 'gray', 'slate']
const colorValues = [200, 300, 400, 500, 600, 700, 800, 900,]; const colorValues = [200, 300, 400, 500, 600, 700, 800, 900]
function colorBgClass(color: string, value: number) { function colorBgClass(color: string, value: number) {
return `bg-${color}-${value}`; return `bg-${color}-${value}`
} }
function log(data: any) { function log(data: any) {
console.log(data); console.log(data)
} }
</script> </script>
<template> <template>
@ -75,142 +72,190 @@ function log(data: any) {
<h2 class="heading-1">Icons</h2> <h2 class="heading-1">Icons</h2>
</div> </div>
<p class="mt-8 text-xl">The icons are defined as Web Components, so they can also be used in the backend. Use them like <p class="mt-8 text-xl">
&lt;it-icon-message/&gt; </p> The icons are defined as Web Components, so they can also be used in the backend. Use them like
&lt;it-icon-message/&gt;
</p>
<div class="mt-8 mb-8 flex flex-col gap-4 flex-wrap lg:flex-row"> <div class="mt-8 mb-8 flex flex-col gap-4 flex-wrap lg:flex-row">
<div class="inline-flex flex-col"> <div class="inline-flex flex-col">
message message
<it-icon-message class="it-icon"/> <it-icon-message class="it-icon" />
</div> </div>
<div class="inline-flex flex-col"> <div class="inline-flex flex-col">
arrow-up arrow-up
<it-icon-arrow-up/> <it-icon-arrow-up />
</div> </div>
<div class="inline-flex flex-col"> <div class="inline-flex flex-col">
arrow-down arrow-down
<it-icon-arrow-down/> <it-icon-arrow-down />
</div> </div>
<div class="inline-flex flex-col"> <div class="inline-flex flex-col">
arrow-left arrow-left
<it-icon-arrow-left/> <it-icon-arrow-left />
</div> </div>
<div class="inline-flex flex-col"> <div class="inline-flex flex-col">
arrow-right arrow-right
<it-icon-arrow-right/> <it-icon-arrow-right />
</div> </div>
<div class="inline-flex flex-col"> <div class="inline-flex flex-col">
close close
<it-icon-close/> <it-icon-close />
</div> </div>
<div class="inline-flex flex-col"> <div class="inline-flex flex-col">
check check
<it-icon-check/> <it-icon-check />
</div> </div>
<div class="inline-flex flex-col"> <div class="inline-flex flex-col">
info info
<it-icon-info/> <it-icon-info />
</div> </div>
<div class="inline-flex flex-col"> <div class="inline-flex flex-col">
list list
<it-icon-list/> <it-icon-list />
</div> </div>
<div class="inline-flex flex-col"> <div class="inline-flex flex-col">
menu menu
<it-icon-menu/> <it-icon-menu />
</div> </div>
</div> </div>
<div class="mt-8 mb-8 flex flex-col gap-4 flex-wrap lg:flex-row"> <div class="mt-8 mb-8 flex flex-col gap-4 flex-wrap lg:flex-row">
<div class="inline-flex flex-col"> <div class="inline-flex flex-col">
ls-apply ls-apply
<it-icon-ls-apply/> <it-icon-ls-apply />
</div> </div>
<div class="inline-flex flex-col"> <div class="inline-flex flex-col">
ls-watch ls-watch
<it-icon-ls-watch/> <it-icon-ls-watch />
</div> </div>
<div class="inline-flex flex-col"> <div class="inline-flex flex-col">
ls-test ls-test
<it-icon-ls-test/> <it-icon-ls-test />
</div> </div>
<div class="inline-flex flex-col"> <div class="inline-flex flex-col">
ls-practice ls-practice
<it-icon-ls-practice/> <it-icon-ls-practice />
</div> </div>
<div class="inline-flex flex-col"> <div class="inline-flex flex-col">
ls-network ls-network
<it-icon-ls-network/> <it-icon-ls-network />
</div> </div>
<div class="inline-flex flex-col"> <div class="inline-flex flex-col">
ls-start ls-start
<it-icon-ls-start/> <it-icon-ls-start />
</div> </div>
<div class="inline-flex flex-col"> <div class="inline-flex flex-col">
ls-end ls-end
<it-icon-ls-end/> <it-icon-ls-end />
</div> </div>
</div> </div>
<div class="mt-8 mb-8 flex flex-col gap-4 flex-wrap lg:flex-row">
<div class="inline-flex flex-col">
lc-assignment
<it-icon-lc-assignment />
</div>
<div class="inline-flex flex-col">
lc-book
<it-icon-lc-book />
</div>
<div class="inline-flex flex-col">
lc-document
<it-icon-lc-document />
</div>
<div class="inline-flex flex-col">
lc-exercise
<it-icon-lc-exercise />
</div>
<div class="inline-flex flex-col">
lc-media-library
<it-icon-lc-media-library />
</div>
<div class="inline-flex flex-col">
lc-online-training
<it-icon-lc-online-training />
</div>
<div class="inline-flex flex-col">
lc-resource
<it-icon-lc-resource />
</div>
<div class="inline-flex flex-col">
lc-test
<it-icon-lc-test />
</div>
<div class="inline-flex flex-col">
lc-video
<it-icon-lc-video />
</div>
</div>
<div class="mt-8 mb-8 flex flex-col gap-4 flex-wrap lg:flex-row"> <div class="mt-8 mb-8 flex flex-col gap-4 flex-wrap lg:flex-row">
<div class="inline-flex flex-col"> <div class="inline-flex flex-col">
smiley-happy smiley-happy
<it-icon-smiley-happy/> <it-icon-smiley-happy />
</div> </div>
<div class="inline-flex flex-col"> <div class="inline-flex flex-col">
smiley-thinking smiley-thinking
<it-icon-smiley-thinking/> <it-icon-smiley-thinking />
</div> </div>
<div class="inline-flex flex-col"> <div class="inline-flex flex-col">
smiley-neutral smiley-neutral
<it-icon-smiley-neutral/> <it-icon-smiley-neutral />
</div> </div>
</div> </div>
<div class="mt-8 mb-8 flex flex-col gap-4 flex-wrap lg:flex-row"> <div class="mt-8 mb-8 flex flex-col gap-4 flex-wrap lg:flex-row">
<div class="inline-flex flex-col text-orange-500"> <div class="inline-flex flex-col text-orange-500">
message big message big
<it-icon-message class="w-16 h-16 text-orange-500"/> <it-icon-message class="w-16 h-16 text-orange-500" />
</div> </div>
<div class="inline-flex flex-col text-blue-400"> <div class="inline-flex flex-col text-blue-400">
ls-network big ls-network big
<it-icon-ls-network class="w-16 h-16"/> <it-icon-ls-network class="w-16 h-16" />
</div> </div>
<div class="inline-flex flex-col text-red-500"> <div class="inline-flex flex-col text-red-500">
close small close small
<it-icon-close class="w-6 h-6"/> <it-icon-close class="w-6 h-6" />
</div> </div>
<div class="inline-flex flex-col text-white bg-blue-900"> <div class="inline-flex flex-col text-white bg-blue-900">
vbv vbv
<it-icon-vbv class="w-24 h-24"/> <it-icon-vbv class="w-24 h-24" />
</div> </div>
<div class="inline-flex flex-col"> <div class="inline-flex flex-col">
vbv-pos vbv-pos
<it-icon-vbv-pos class="w-24 h-24"/> <it-icon-vbv-pos class="w-24 h-24" />
</div> </div>
</div> </div>
<div class="border-b text-gray-700 pb-2 mt-8"> <div class="border-b text-gray-700 pb-2 mt-8">
@ -219,10 +264,10 @@ function log(data: any) {
<table class="text-gray-700"> <table class="text-gray-700">
<tr class="h-12 md:h-18 lg:h-24"> <tr class="h-12 md:h-18 lg:h-24">
<td></td> <td></td>
<td class="text-center" v-for="value in colorValues">{{value}}</td> <td class="text-center" v-for="value in colorValues">{{ value }}</td>
</tr> </tr>
<tr v-for="color in colors" class="h-12 md:h-18 lg:h-24"> <tr v-for="color in colors" class="h-12 md:h-18 lg:h-24">
<td>{{color}}</td> <td>{{ color }}</td>
<td v-for="value in colorValues" class="px-2"> <td v-for="value in colorValues" class="px-2">
<div class="w-8 h-8 md:w-12 md:h-12 lg:w-16 lg:h-16 rounded-full" :class="[colorBgClass(color, value)]"></div> <div class="w-8 h-8 md:w-12 md:h-12 lg:w-16 lg:h-16 rounded-full" :class="[colorBgClass(color, value)]"></div>
</td> </td>
@ -267,29 +312,24 @@ function log(data: any) {
</div> </div>
<div class="flex flex-col gap-4 flex-wrap lg:flex-row content-center lg:justify-start mb-16"> <div class="flex flex-col gap-4 flex-wrap lg:flex-row content-center lg:justify-start mb-16">
<button type="button" <button type="button" class="btn-primary inline-flex items-center p-3 rounded-full">
class="btn-primary inline-flex items-center p-3 rounded-full">
<it-icon-message class="h-5 w-5"></it-icon-message> <it-icon-message class="h-5 w-5"></it-icon-message>
</button> </button>
<button type="button" <button type="button" class="btn-primary inline-flex items-center px-3 py-2">
class="btn-primary inline-flex items-center px-3 py-2">
<it-icon-message class="-ml-1 mr-3 h-5 w-5"></it-icon-message> <it-icon-message class="-ml-1 mr-3 h-5 w-5"></it-icon-message>
Button text Button text
</button> </button>
<button type="button" <button type="button" class="btn-primary inline-flex items-center px-3 py-2">
class="btn-primary inline-flex items-center px-3 py-2">
Button text Button text
<it-icon-message class="ml-3 -mr-1 h-5 w-5"></it-icon-message> <it-icon-message class="ml-3 -mr-1 h-5 w-5"></it-icon-message>
</button> </button>
<button type="button" <button type="button" class="btn-text inline-flex items-center px-3 py-2">
class="btn-text inline-flex items-center px-3 py-2">
<it-icon-message class="-ml-1 mr-3 h-5 w-5"></it-icon-message> <it-icon-message class="-ml-1 mr-3 h-5 w-5"></it-icon-message>
Button text Button text
</button> </button>
</div> </div>
<h2 class="mt-8 mb-8">Dropdown (Work-in-progress)</h2> <h2 class="mt-8 mb-8">Dropdown (Work-in-progress)</h2>
@ -297,28 +337,47 @@ function log(data: any) {
<Listbox as="div" v-model="state.dropdownSelected"> <Listbox as="div" v-model="state.dropdownSelected">
<div class="mt-1 relative w-128"> <div class="mt-1 relative w-128">
<ListboxButton <ListboxButton
class="bg-white relative w-full border border-gray-500 pl-5 pr-10 py-3 text-left cursor-default font-bold"> class="bg-white relative w-full border border-gray-500 pl-5 pr-10 py-3 text-left cursor-default font-bold"
>
<span class="block truncate">{{ state.dropdownSelected.name }}</span> <span class="block truncate">{{ state.dropdownSelected.name }}</span>
<span class="absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none"> <span class="absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none">
<it-icon-arrow-down class="h-5 w-5" aria-hidden="true"/> <it-icon-arrow-down class="h-5 w-5" aria-hidden="true" />
</span> </span>
</ListboxButton> </ListboxButton>
<transition leave-active-class="transition ease-in duration-100" leave-from-class="opacity-100" <transition
leave-to-class="opacity-0"> leave-active-class="transition ease-in duration-100"
leave-from-class="opacity-100"
leave-to-class="opacity-0"
>
<ListboxOptions <ListboxOptions
class="absolute z-10 mt-1 w-full bg-white shadow-lg max-h-60 py-1 text-base ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none sm:text-sm"> class="absolute z-10 mt-1 w-full bg-white shadow-lg max-h-60 py-1 text-base ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none sm:text-sm"
<ListboxOption as="template" v-for="person in state.dropdownValues" :key="person.id" :value="person" >
v-slot="{ active, selected }"> <ListboxOption
as="template"
v-for="person in state.dropdownValues"
:key="person.id"
:value="person"
v-slot="{ active, selected }"
>
<li <li
:class="[active ? 'text-white bg-blue-900' : 'text-black', 'cursor-default select-none relative py-2 pl-3 pr-9']"> :class="[
active ? 'text-white bg-blue-900' : 'text-black',
'cursor-default select-none relative py-2 pl-3 pr-9',
]"
>
<span :class="[state.dropdownSelected ? 'font-semibold' : 'font-normal', 'block truncate']"> <span :class="[state.dropdownSelected ? 'font-semibold' : 'font-normal', 'block truncate']">
{{ person.name }} {{ person.name }}
</span> </span>
<span v-if="state.dropdownSelected" <span
:class="[active ? 'text-white' : 'text-blue-900', 'absolute inset-y-0 right-0 flex items-center pr-4']"> v-if="state.dropdownSelected"
<it-icon-check class="h-5 w-5" aria-hidden="true"/> :class="[
active ? 'text-white' : 'text-blue-900',
'absolute inset-y-0 right-0 flex items-center pr-4',
]"
>
<it-icon-check class="h-5 w-5" aria-hidden="true" />
</span> </span>
</li> </li>
</ListboxOption> </ListboxOption>
@ -336,16 +395,11 @@ function log(data: any) {
<h2 class="mt-8 mb-8">Dropdown</h2> <h2 class="mt-8 mb-8">Dropdown</h2>
<div class="h-60"> <div class="h-60">
<ItDropdown <ItDropdown :button-classes="['btn-primary']" :list-items="dropdownData" :align="'left'" @select="log"
:button-classes="['btn-primary']" >Click Me</ItDropdown
:list-items="dropdownData" >
:align="'left'"
@select="log"
>Click Me</ItDropdown>
</div> </div>
</main> </main>
</template> </template>
<style scoped> <style scoped></style>
</style>

View File

@ -8,8 +8,9 @@ from vbv_lernwelt.core.admin import User
from vbv_lernwelt.learnpath.models import LearningPath, Topic, Circle, LearningSequence, LearningContent, LearningUnit, \ from vbv_lernwelt.learnpath.models import LearningPath, Topic, Circle, LearningSequence, LearningContent, LearningUnit, \
LearningUnitQuestion LearningUnitQuestion
from vbv_lernwelt.learnpath.tests.learning_path_factories import LearningPathFactory, TopicFactory, CircleFactory, \ from vbv_lernwelt.learnpath.tests.learning_path_factories import LearningPathFactory, TopicFactory, CircleFactory, \
LearningSequenceFactory, LearningContentFactory, VideoBlockFactory, PodcastBlockFactory, CompetenceBlockFactory, \ LearningSequenceFactory, LearningContentFactory, VideoBlockFactory, ResourceBlockFactory, \
ExerciseBlockFactory, DocumentBlockFactory, LearningUnitFactory, LearningUnitQuestionFactory ExerciseBlockFactory, DocumentBlockFactory, LearningUnitFactory, LearningUnitQuestionFactory, \
AssignmentBlockFactory, BookBlockFactory, MediaLibraryBlockFactory, OnlineTrainingBlockFactory, TestBlockFactory
def create_circle(title, learning_path): def create_circle(title, learning_path):
@ -73,7 +74,7 @@ def create_circle_children(circle, title):
title='Ermittlung des Kundenbedarfs', title='Ermittlung des Kundenbedarfs',
parent=circle, parent=circle,
minutes=30, minutes=30,
contents=[('podcast', PodcastBlockFactory( contents=[('video', VideoBlockFactory(
description='Die Ermittlung des Kundenbedarfs muss in einem eingehenden Gespräch herausgefunden werden. Höre dazu auch diesen Podcast an.', description='Die Ermittlung des Kundenbedarfs muss in einem eingehenden Gespräch herausgefunden werden. Höre dazu auch diesen Podcast an.',
url='https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/325190984&color=%23ff5500&auto_play=false&hide_related=false&show_comments=true&show_user=true&show_reposts=false&show_teaser=true&visual=true', url='https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/325190984&color=%23ff5500&auto_play=false&hide_related=false&show_comments=true&show_user=true&show_reposts=false&show_teaser=true&visual=true',
))] ))]
@ -106,7 +107,7 @@ def create_circle_children(circle, title):
title='Kundenbedürfnisse erkennen', title='Kundenbedürfnisse erkennen',
parent=circle, parent=circle,
minutes=30, minutes=30,
contents=[('competence', CompetenceBlockFactory())] contents=[('exercise', ExerciseBlockFactory())]
) )
LearningContentFactory( LearningContentFactory(
@ -164,13 +165,13 @@ def create_circle_children(circle, title):
title='Motorfahrzeugversicherung', title='Motorfahrzeugversicherung',
parent=circle, parent=circle,
minutes=240, minutes=240,
contents=[('competence', CompetenceBlockFactory())] contents=[('assignment', AssignmentBlockFactory())]
) )
LearningContentFactory( LearningContentFactory(
title='Nora kauft sich ein neues Auto', title='Nora kauft sich ein neues Auto',
parent=circle, parent=circle,
minutes=60, minutes=60,
contents=[('podcast', PodcastBlockFactory())] contents=[('resource', ResourceBlockFactory())]
) )
LearningContentFactory( LearningContentFactory(
title='Ermittlung des Kundenbedarfs', title='Ermittlung des Kundenbedarfs',
@ -194,13 +195,13 @@ def create_circle_children(circle, title):
title='3-Säulen-Prinzip', title='3-Säulen-Prinzip',
parent=circle, parent=circle,
minutes=240, minutes=240,
contents=[('competence', CompetenceBlockFactory())] contents=[('test', TestBlockFactory())]
) )
LearningContentFactory( LearningContentFactory(
title='Altersvorsorge', title='Altersvorsorge',
parent=circle, parent=circle,
minutes=240, minutes=240,
contents=[('competence', CompetenceBlockFactory())] contents=[('test', TestBlockFactory())]
) )
LearningContentFactory( LearningContentFactory(
title='AHV', title='AHV',
@ -224,7 +225,7 @@ def create_circle_children(circle, title):
title='Reiseversicherung', title='Reiseversicherung',
parent=circle, parent=circle,
minutes=240, minutes=240,
contents=[('competence', CompetenceBlockFactory())] contents=[('exercise', ExerciseBlockFactory())]
) )
LearningContentFactory( LearningContentFactory(
title='Sorgenfrei reisen', title='Sorgenfrei reisen',
@ -243,7 +244,7 @@ def create_circle_children(circle, title):
title='Privathaftpflicht', title='Privathaftpflicht',
parent=circle, parent=circle,
minutes=240, minutes=240,
contents=[('competence', CompetenceBlockFactory())] contents=[('media_library', MediaLibraryBlockFactory())]
) )
LearningContentFactory( LearningContentFactory(
title='Zusatzversicherung', title='Zusatzversicherung',
@ -268,19 +269,19 @@ def create_circle_children(circle, title):
title='Hausrat', title='Hausrat',
parent=circle, parent=circle,
minutes=120, minutes=120,
contents=[('competence', CompetenceBlockFactory())] contents=[('online_training', OnlineTrainingBlockFactory())]
) )
LearningContentFactory( LearningContentFactory(
title='Privathaftpflicht', title='Privathaftpflicht',
parent=circle, parent=circle,
minutes=60, minutes=60,
contents=[('competence', CompetenceBlockFactory())] contents=[('exercise', ExerciseBlockFactory())]
) )
LearningContentFactory( LearningContentFactory(
title='Kind zieht von zu Hause wirklich aus', title='Kind zieht von zu Hause wirklich aus',
parent=circle, parent=circle,
minutes=60, minutes=60,
contents=[('competence', CompetenceBlockFactory())] contents=[('exercise', ExerciseBlockFactory())]
) )
LearningSequenceFactory(title='Testen', parent=circle, icon='it-icon-ls-test') LearningSequenceFactory(title='Testen', parent=circle, icon='it-icon-ls-test')
@ -293,13 +294,13 @@ def create_circle_children(circle, title):
title='Das erwartet dich im Test', title='Das erwartet dich im Test',
parent=circle, parent=circle,
minutes=30, minutes=30,
contents=[('document', CompetenceBlockFactory())] contents=[('test', TestBlockFactory())]
) )
LearningContentFactory( LearningContentFactory(
title='Test durchführen', title='Test durchführen',
parent=circle, parent=circle,
minutes=30, minutes=30,
contents=[('document', CompetenceBlockFactory())] contents=[('test', TestBlockFactory())]
) )
LearningSequenceFactory(title='Vernetzen', parent=circle, icon='it-icon-ls-network') LearningSequenceFactory(title='Vernetzen', parent=circle, icon='it-icon-ls-network')
@ -307,21 +308,21 @@ def create_circle_children(circle, title):
title='Online Training', title='Online Training',
parent=circle, parent=circle,
minutes=60, minutes=60,
contents=[('document', CompetenceBlockFactory())] contents=[('online_training', OnlineTrainingBlockFactory())]
) )
LearningSequenceFactory(title='Beenden', parent=circle, icon='it-icon-ls-end') LearningSequenceFactory(title='Beenden', parent=circle, icon='it-icon-ls-end')
LearningContentFactory( LearningContentFactory(
title='Kompetenzprofil anschauen', title='Mehr darüber erfahren',
parent=circle, parent=circle,
minutes=30, minutes=30,
contents=[('document', CompetenceBlockFactory())] contents=[('book', BookBlockFactory())]
) )
LearningContentFactory( LearningContentFactory(
title='Circle "Analyse" abschliessen', title='Circle "Analyse" abschliessen',
parent=circle, parent=circle,
minutes=30, minutes=30,
contents=[('document', CompetenceBlockFactory())] contents=[('document', DocumentBlockFactory())]
) )
@ -369,13 +370,13 @@ damit erfolgreich mit deinem Lernpfad starten kannst.
title='Kompetenzprofil anschauen', title='Kompetenzprofil anschauen',
parent=circle_basis, parent=circle_basis,
minutes=30, minutes=30,
contents=[('document', CompetenceBlockFactory())] contents=[('document', DocumentBlockFactory())]
) )
LearningContentFactory( LearningContentFactory(
title='Circle "Analyse" abschliessen', title='Circle "Analyse" abschliessen',
parent=circle_basis, parent=circle_basis,
minutes=30, minutes=30,
contents=[('document', CompetenceBlockFactory())] contents=[('document', DocumentBlockFactory())]
) )
TopicFactory(title="Gewinnen von Kunden", parent=lp) TopicFactory(title="Gewinnen von Kunden", parent=lp)

View File

@ -5,10 +5,11 @@ from wagtail.admin.panels import FieldPanel, StreamFieldPanel
from wagtail.blocks import StreamBlock from wagtail.blocks import StreamBlock
from wagtail.fields import StreamField from wagtail.fields import StreamField
from wagtail.images.blocks import ImageChooserBlock from wagtail.images.blocks import ImageChooserBlock
from wagtail.models import Page, Orderable from wagtail.models import Page
from vbv_lernwelt.learnpath.models_learning_unit_content import WebBasedTrainingBlock, VideoBlock, PodcastBlock, \ from vbv_lernwelt.learnpath.models_learning_unit_content import VideoBlock, \
CompetenceBlock, ExerciseBlock, DocumentBlock, KnowledgeBlock ExerciseBlock, DocumentBlock, AssignmentBlock, BookBlock, MediaLibraryBlock, \
OnlineTrainingBlock, ResourceBlock, TestBlock
from vbv_lernwelt.learnpath.serializer_helpers import get_it_serializer_class from vbv_lernwelt.learnpath.serializer_helpers import get_it_serializer_class
@ -208,12 +209,14 @@ class LearningContent(Page):
content_blocks = [ content_blocks = [
('video', VideoBlock()), ('video', VideoBlock()),
('web_based_training', WebBasedTrainingBlock()), ('resource', ResourceBlock()),
('podcast', PodcastBlock()),
('competence', CompetenceBlock()),
('exercise', ExerciseBlock()), ('exercise', ExerciseBlock()),
('online_training', OnlineTrainingBlock()),
('media_library', MediaLibraryBlock()),
('document', DocumentBlock()), ('document', DocumentBlock()),
('knowledge', KnowledgeBlock()), ('test', TestBlock()),
('book', BookBlock()),
('assignment', AssignmentBlock()),
] ]
contents = StreamField( contents = StreamField(

View File

@ -1,5 +1,60 @@
from wagtail import blocks from wagtail import blocks
class AssignmentBlock(blocks.StructBlock):
description = blocks.TextBlock()
url = blocks.URLBlock()
class Meta:
icon = 'media'
class BookBlock(blocks.StructBlock):
description = blocks.TextBlock()
url = blocks.URLBlock()
class Meta:
icon = 'media'
class DocumentBlock(blocks.StructBlock):
description = blocks.TextBlock()
url = blocks.URLBlock()
class Meta:
icon = 'media'
class ExerciseBlock(blocks.StructBlock):
description = blocks.TextBlock()
url = blocks.URLBlock()
class Meta:
icon = 'media'
class MediaLibraryBlock(blocks.StructBlock):
description = blocks.TextBlock()
url = blocks.URLBlock()
class Meta:
icon = 'media'
class OnlineTrainingBlock(blocks.StructBlock):
description = blocks.TextBlock()
url = blocks.URLBlock()
class Meta:
icon = 'media'
class ResourceBlock(blocks.StructBlock):
description = blocks.TextBlock()
url = blocks.URLBlock()
class Meta:
icon = 'media'
class TestBlock(blocks.StructBlock):
description = blocks.TextBlock()
url = blocks.URLBlock()
class Meta:
icon = 'media'
class VideoBlock(blocks.StructBlock): class VideoBlock(blocks.StructBlock):
# TODO: Possible video Types for the user, upload file, add URL # TODO: Possible video Types for the user, upload file, add URL
@ -8,50 +63,3 @@ class VideoBlock(blocks.StructBlock):
class Meta: class Meta:
icon = 'media' icon = 'media'
class WebBasedTrainingBlock(blocks.StructBlock):
description = blocks.TextBlock()
url = blocks.URLBlock()
class Meta:
icon = 'media'
class PodcastBlock(blocks.StructBlock):
description = blocks.TextBlock()
url = blocks.URLBlock()
class Meta:
icon = 'media'
class CompetenceBlock(blocks.StructBlock):
description = blocks.TextBlock()
class Meta:
icon = 'media'
class ExerciseBlock(blocks.StructBlock):
description = blocks.TextBlock()
url = blocks.URLBlock()
class Meta:
icon = 'media'
class DocumentBlock(blocks.StructBlock):
description = blocks.TextBlock()
class Meta:
icon = 'media'
class KnowledgeBlock(blocks.StructBlock):
description = blocks.TextBlock()
class Meta:
icon = 'media'

View File

@ -1,11 +1,11 @@
import wagtail_factories import wagtail_factories
from django.conf import settings from django.conf import settings
from wagtail.models import Site, Page from wagtail.models import Site, Page
from vbv_lernwelt.core.admin import User from vbv_lernwelt.core.admin import User
from vbv_lernwelt.learnpath.tests.learning_path_factories import LearningPathFactory, TopicFactory, CircleFactory, \ from vbv_lernwelt.learnpath.tests.learning_path_factories import LearningPathFactory, TopicFactory, CircleFactory, \
LearningSequenceFactory, LearningContentFactory, CompetenceBlockFactory, \ LearningSequenceFactory, LearningContentFactory, \
ExerciseBlockFactory, LearningUnitFactory, LearningUnitQuestionFactory ExerciseBlockFactory, LearningUnitFactory, LearningUnitQuestionFactory, \
DocumentBlockFactory, TestBlockFactory, OnlineTrainingBlockFactory
def create_circle(title, learning_path): def create_circle(title, learning_path):
@ -33,7 +33,7 @@ def create_circle_children(circle, title):
title=f'Einleitung Circle "{title}"', title=f'Einleitung Circle "{title}"',
parent=circle, parent=circle,
minutes=15, minutes=15,
contents=[('competence', CompetenceBlockFactory())] contents=[('document', DocumentBlockFactory())]
) )
LearningSequenceFactory(title='Beobachten', parent=circle, icon='it-icon-ls-watch') LearningSequenceFactory(title='Beobachten', parent=circle, icon='it-icon-ls-watch')
@ -53,13 +53,16 @@ def create_circle_children(circle, title):
title='Ermittlung des Kundenbedarfs', title='Ermittlung des Kundenbedarfs',
parent=circle, parent=circle,
minutes=30, minutes=30,
contents=[('competence', CompetenceBlockFactory())] contents=[('online_training', OnlineTrainingBlockFactory(
description='In diesem Online-Training lernst du, wie du den Kundenbedarf ermittelst.',
url='',
))]
) )
LearningContentFactory( LearningContentFactory(
title='Kundenbedürfnisse erkennen', title='Kundenbedürfnisse erkennen',
parent=circle, parent=circle,
minutes=30, minutes=30,
contents=[('competence', CompetenceBlockFactory())] contents=[('test', TestBlockFactory())]
) )
LearningContentFactory( LearningContentFactory(
title='Was braucht eine Familie?', title='Was braucht eine Familie?',
@ -79,7 +82,7 @@ def create_circle_children(circle, title):
title='Reiseversicherung', title='Reiseversicherung',
parent=circle, parent=circle,
minutes=240, minutes=240,
contents=[('competence', CompetenceBlockFactory())] contents=[('exercise', ExerciseBlockFactory())]
) )
LearningContentFactory( LearningContentFactory(
title='Sorgenfrei reisen', title='Sorgenfrei reisen',
@ -94,13 +97,13 @@ def create_circle_children(circle, title):
title='Kompetenzprofil anschauen', title='Kompetenzprofil anschauen',
parent=circle, parent=circle,
minutes=30, minutes=30,
contents=[('document', CompetenceBlockFactory())] contents=[('document', DocumentBlockFactory())]
) )
LearningContentFactory( LearningContentFactory(
title='Circle "Analyse" abschliessen', title='Circle "Analyse" abschliessen',
parent=circle, parent=circle,
minutes=30, minutes=30,
contents=[('document', CompetenceBlockFactory())] contents=[('document', DocumentBlockFactory())]
) )
@ -131,20 +134,20 @@ def create_simple_test_learning_path(user=None, skip_locales=True):
title='Einleitung Circle "Basis"', title='Einleitung Circle "Basis"',
parent=circle_basis, parent=circle_basis,
minutes=15, minutes=15,
contents=[('competence', CompetenceBlockFactory())] contents=[('document', DocumentBlockFactory())]
) )
LearningSequenceFactory(title='Beenden', parent=circle_basis, icon='it-icon-ls-end') LearningSequenceFactory(title='Beenden', parent=circle_basis, icon='it-icon-ls-end')
LearningContentFactory( LearningContentFactory(
title='Kompetenzprofil anschauen', title='Kompetenzprofil anschauen',
parent=circle_basis, parent=circle_basis,
minutes=30, minutes=30,
contents=[('document', CompetenceBlockFactory())] contents=[('document', DocumentBlockFactory())]
) )
LearningContentFactory( LearningContentFactory(
title='Circle "Analyse" abschliessen', title='Circle "Analyse" abschliessen',
parent=circle_basis, parent=circle_basis,
minutes=30, minutes=30,
contents=[('document', CompetenceBlockFactory())] contents=[('document', DocumentBlockFactory())]
) )
TopicFactory(title="Gewinnen von Kunden", parent=lp) TopicFactory(title="Gewinnen von Kunden", parent=lp)

View File

@ -2,8 +2,8 @@ import wagtail_factories
from vbv_lernwelt.learnpath.models import LearningPath, Topic, Circle, LearningSequence, LearningContent, LearningUnit, \ from vbv_lernwelt.learnpath.models import LearningPath, Topic, Circle, LearningSequence, LearningContent, LearningUnit, \
LearningUnitQuestion LearningUnitQuestion
from vbv_lernwelt.learnpath.models_learning_unit_content import VideoBlock, WebBasedTrainingBlock, PodcastBlock, \ from vbv_lernwelt.learnpath.models_learning_unit_content import VideoBlock, OnlineTrainingBlock, \
CompetenceBlock, ExerciseBlock, DocumentBlock, KnowledgeBlock ExerciseBlock, DocumentBlock, ResourceBlock, TestBlock, BookBlock, MediaLibraryBlock, AssignmentBlock
class LearningPathFactory(wagtail_factories.PageFactory): class LearningPathFactory(wagtail_factories.PageFactory):
@ -48,7 +48,6 @@ class LearningUnitQuestionFactory(wagtail_factories.PageFactory):
class Meta: class Meta:
model = LearningUnitQuestion model = LearningUnitQuestion
class LearningContentFactory(wagtail_factories.PageFactory): class LearningContentFactory(wagtail_factories.PageFactory):
title = 'Lerninhalt' title = 'Lerninhalt'
@ -63,37 +62,17 @@ class VideoBlockFactory(wagtail_factories.StructBlockFactory):
class Meta: class Meta:
model = VideoBlock model = VideoBlock
class AssignmentBlockFactory(wagtail_factories.StructBlockFactory):
class WebBasedTrainingBlockFactory(wagtail_factories.StructBlockFactory): description = "Beispiel Auftrag"
url = "/static/media/web_based_trainings/rise_cmi5_test_export/scormcontent/index.html"
description = "Beispiel Rise Modul"
class Meta: class Meta:
model = WebBasedTrainingBlock model = AssignmentBlock
class BookBlockFactory(wagtail_factories.StructBlockFactory):
class PodcastBlockFactory(wagtail_factories.StructBlockFactory): description = "Beispiel Buch"
description = "Beispiel Podcast"
url = "https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/325190984&color=%23ff5500&auto_play=false&hide_related=false&show_comments=true&show_user=true&show_reposts=false&show_teaser=true&visual=true"
class Meta: class Meta:
model = PodcastBlock model = BookBlock
class CompetenceBlockFactory(wagtail_factories.StructBlockFactory):
description = "Beispiel Kompetenz"
class Meta:
model = CompetenceBlock
class ExerciseBlockFactory(wagtail_factories.StructBlockFactory):
description = "Beispiel Aufgabe"
url = "/static/media/web_based_trainings/rise_cmi5_test_export/scormcontent/index.html"
class Meta:
model = ExerciseBlock
class DocumentBlockFactory(wagtail_factories.StructBlockFactory): class DocumentBlockFactory(wagtail_factories.StructBlockFactory):
description = "Beispiel Dokument" description = "Beispiel Dokument"
@ -101,9 +80,33 @@ class DocumentBlockFactory(wagtail_factories.StructBlockFactory):
class Meta: class Meta:
model = DocumentBlock model = DocumentBlock
class ExerciseBlockFactory(wagtail_factories.StructBlockFactory):
class KnowledgeBlockFactory(wagtail_factories.StructBlockFactory): description = "Beispiel Übung"
description = "Beispiel Wissen"
class Meta: class Meta:
model = KnowledgeBlock model = ExerciseBlock
class OnlineTrainingBlockFactory(wagtail_factories.StructBlockFactory):
url = "/static/media/web_based_trainings/rise_cmi5_test_export/scormcontent/index.html"
description = "Beispiel Rise Modul"
class Meta:
model = OnlineTrainingBlock
class TestBlockFactory(wagtail_factories.StructBlockFactory):
description = "Beispiel Test"
class Meta:
model = TestBlock
class ResourceBlockFactory(wagtail_factories.StructBlockFactory):
description = "Beispiel Hilfsmittel"
class Meta:
model = ResourceBlock
class MediaLibraryBlockFactory(wagtail_factories.StructBlockFactory):
description = "Beispiel Mediathekeninhalt"
class Meta:
model = MediaLibraryBlock

View File

@ -1 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?><svg id="a" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30"><path d="M15,24.77c-5.39,0-9.77-4.38-9.77-9.77S9.61,5.23,15,5.23s9.77,4.38,9.77,9.77-4.38,9.77-9.77,9.77Zm0-18.04c-4.56,0-8.27,3.71-8.27,8.27s3.71,8.27,8.27,8.27,8.27-3.71,8.27-8.27-3.71-8.27-8.27-8.27Z"/><rect x="14.25" y="14" width="1.5" height="6"/><rect x="14.25" y="10.5" width="1.5" height="1.5"/></svg> <?xml version="1.0" encoding="UTF-8"?>
<svg id="a" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30">
<path d="M15,24.77c-5.39,0-9.77-4.38-9.77-9.77S9.61,5.23,15,5.23s9.77,4.38,9.77,9.77-4.38,9.77-9.77,9.77Zm0-18.04c-4.56,0-8.27,3.71-8.27,8.27s3.71,8.27,8.27,8.27,8.27-3.71,8.27-8.27-3.71-8.27-8.27-8.27Z"/>
<rect x="14.25" y="14" width="1.5" height="6"/>
<rect x="14.25" y="10.5" width="1.5" height="1.5"/>
</svg>

Before

Width:  |  Height:  |  Size: 414 B

After

Width:  |  Height:  |  Size: 432 B

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg id="a" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30"><path d="M23.45,3.84h-1.25v-.93c0-.41-.34-.75-.75-.75H8.55c-.41,0-.75,.34-.75,.75v.93h-1.25c-1.24,0-2.25,1.01-2.25,2.25V25.59c0,1.24,1.01,2.25,2.25,2.25H23.45c1.24,0,2.25-1.01,2.25-2.25V6.09c0-1.24-1.01-2.25-2.25-2.25Zm-14.15-.18h11.4v1.86H9.3v-1.86Zm14.9,21.94c0,.41-.34,.75-.75,.75H6.55c-.41,0-.75-.34-.75-.75V6.09c0-.41,.34-.75,.75-.75h1.25v.93c0,.41,.34,.75,.75,.75h12.9c.41,0,.75-.34,.75-.75v-.93h1.25c.41,0,.75,.34,.75,.75V25.59Z"/><rect x="11.81" y="10.69" width="9.97" height="1.5"/><rect x="8.22" y="10.69" width="1.5" height="1.5"/><rect x="11.81" y="15.45" width="9.97" height="1.5"/><rect x="8.22" y="15.45" width="1.5" height="1.5"/><rect x="11.81" y="20.21" width="9.97" height="1.5"/><rect x="8.22" y="20.21" width="1.5" height="1.5"/></svg>

After

Width:  |  Height:  |  Size: 861 B

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg id="a" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30"><path d="M24.05,22.22c.41,0,.75-.34,.75-.75V2.89c0-.41-.34-.75-.75-.75H7.98c-1.92,0-3.49,1.56-3.49,3.49V24.38h.02c0,1.92,1.56,3.49,3.49,3.49H24.76v-1.5h-1.73v-4.14h1.01ZM5.99,5.63c0-1.1,.89-1.99,1.99-1.99h15.32V20.72H7.99c-.75,0-1.44,.24-2,.63V5.63Zm15.55,20.74H7.99c-1.1,0-1.99-.89-1.99-1.99v-.17c0-1.1,.89-1.99,1.99-1.99h13.54v4.14Z"/><path d="M9.81,11.01h9.61c.41,0,.75-.34,.75-.75v-3.92c0-.41-.34-.75-.75-.75H9.81c-.41,0-.75,.34-.75,.75v3.92c0,.41,.34,.75,.75,.75Zm.75-3.92h8.11v2.42H10.56v-2.42Z"/></svg>

After

Width:  |  Height:  |  Size: 614 B

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg id="a" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30"><path d="M25.25,10.27c0-.07-.02-.13-.04-.19,0-.02-.01-.05-.03-.07-.04-.08-.08-.16-.15-.22l-7.43-7.43c-.06-.06-.14-.11-.22-.15-.02-.01-.05-.02-.07-.03-.06-.02-.12-.03-.19-.04-.02,0-.03,0-.05,0H7c-1.25,0-2.26,1.01-2.26,2.26V25.61c0,1.25,1.01,2.26,2.26,2.26H23c1.25,0,2.26-1.01,2.26-2.26V10.31s0-.03,0-.05Zm-2.55-.7h-4.11c-.42,0-.76-.34-.76-.76V4.7l2.43,2.43,2.43,2.43Zm.3,16.8H7c-.42,0-.76-.34-.76-.76V4.39c0-.42,.34-.76,.76-.76h9.34v5.17c0,1.25,1.01,2.26,2.26,2.26h5.17v14.54c0,.42-.34,.76-.76,.76Z"/></svg>

After

Width:  |  Height:  |  Size: 611 B

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg id="a" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30"><path d="M10.64,25.4L25.51,6.63c.12-.16,.18-.35,.16-.55-.02-.2-.12-.38-.28-.5l-4.05-3.21c-.33-.26-.8-.2-1.05,.12L5.41,21.25c-.08,.1-.13,.21-.15,.34l-.92,5.32c-.05,.27,.06,.54,.27,.72,.13,.11,.3,.16,.47,.16H24.92v-1.5H8.76l1.58-.67c.12-.05,.22-.13,.29-.22Zm-.71-1.52l-2.88-2.28L18.91,6.64l2.88,2.28-11.85,14.96Zm-3.41-.79l2.07,1.64-2.54,1.08,.47-2.72ZM20.99,4.01l2.88,2.28-1.15,1.45-2.88-2.28,1.15-1.45Z"/></svg>

After

Width:  |  Height:  |  Size: 516 B

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg id="a" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30"><path d="M5.5,26.86h-.85c-1.24,0-2.25-1.01-2.25-2.25V5.27c0-1.24,1.01-2.25,2.25-2.25h.85c1.24,0,2.25,1.01,2.25,2.25V24.61c0,1.24-1.01,2.25-2.25,2.25Zm-.85-22.33c-.41,0-.75,.34-.75,.75V24.61c0,.41,.34,.75,.75,.75h.85c.41,0,.75-.34,.75-.75V5.27c0-.41-.34-.75-.75-.75h-.85Z"/><path d="M12.72,26.75h-.85c-1.24,0-2.25-1.01-2.25-2.25V5.17c0-1.24,1.01-2.25,2.25-2.25h.85c1.24,0,2.25,1.01,2.25,2.25V24.5c0,1.24-1.01,2.25-2.25,2.25Zm-.85-22.33c-.41,0-.75,.34-.75,.75V24.5c0,.41,.34,.75,.75,.75h.85c.41,0,.75-.34,.75-.75V5.17c0-.41-.34-.75-.75-.75h-.85Z"/><path d="M24.19,26.51c-.38,0-.76-.1-1.1-.29-.52-.3-.9-.78-1.06-1.36L16.84,6.24c-.33-1.19,.37-2.44,1.56-2.77l.82-.23c1.19-.33,2.44,.37,2.77,1.56l5.19,18.62c.33,1.19-.37,2.44-1.56,2.77l-.82,.23c-.2,.06-.4,.08-.61,.08ZM19.83,4.66c-.07,0-.13,0-.2,.03l-.82,.23c-.4,.11-.63,.53-.52,.92l5.19,18.62c.05,.19,.18,.35,.35,.45,.18,.1,.38,.12,.57,.07l.82-.23h0c.4-.11,.63-.53,.52-.92L20.55,5.21c-.09-.33-.39-.55-.72-.55Z"/></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg id="a" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30"><path d="M24.46,16.32h-.07v-3.33c0-5.18-4.21-9.39-9.4-9.39S5.6,7.81,5.6,12.99v3.33h-.07c-2.07,0-3.75,1.68-3.75,3.75v2.4c0,2.07,1.68,3.75,3.75,3.75h1.42c1.24,0,2.25-1.01,2.25-2.25v-5.4c0-1.19-.93-2.16-2.1-2.23v-3.35c0-4.35,3.54-7.89,7.9-7.89s7.9,3.54,7.9,7.89v3.35c-1.17,.08-2.1,1.05-2.1,2.23v5.4c0,1.24,1.01,2.25,2.25,2.25h1.42c2.07,0,3.75-1.68,3.75-3.75v-2.4c0-2.07-1.68-3.75-3.75-3.75Zm-16.76,2.25v5.4c0,.41-.34,.75-.75,.75h-1.42c-1.24,0-2.25-1.01-2.25-2.25v-2.4c0-1.24,1.01-2.25,2.25-2.25h1.42c.41,0,.75,.34,.75,.75Zm19.01,3.9c0,1.24-1.01,2.25-2.25,2.25h-1.42c-.41,0-.75-.34-.75-.75v-5.4c0-.41,.34-.75,.75-.75h1.42c1.24,0,2.25,1.01,2.25,2.25v2.4Z"/></svg>

After

Width:  |  Height:  |  Size: 763 B

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg id="a" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30"><path d="M20.42,4.17c-2.02-1.64-4.67-2.27-7.27-1.73-3.21,.67-5.84,3.28-6.54,6.48-.56,2.55-.01,5.07,1.53,7.11,.64,.85,1.22,1.75,1.71,2.69l.65,1.24v3.29c0,2.48,2.02,4.5,4.5,4.5s4.5-2.02,4.5-4.5v-3.27l.66-1.25c.45-.85,1-1.72,1.8-2.82,1.08-1.48,1.65-3.23,1.65-5.06,0-2.6-1.16-5.04-3.18-6.68Zm-2.42,18.33h-6v-1.98h6v1.98Zm-3,3.75c-1.39,0-2.56-.96-2.89-2.25h5.79c-.34,1.29-1.5,2.25-2.9,2.25Zm5.75-11.23c-.84,1.16-1.44,2.09-1.92,3.01l-.52,1h-6.61l-.53-1c-.53-1.01-1.15-1.98-1.84-2.89-1.27-1.68-1.72-3.77-1.26-5.89,.58-2.63,2.74-4.78,5.38-5.33,2.15-.46,4.35,.07,6.02,1.42s2.63,3.37,2.63,5.52c0,1.51-.47,2.95-1.36,4.17Z"/></svg>

After

Width:  |  Height:  |  Size: 724 B

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg id="a" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30"><path d="M23.22,27.63H6.78c-1.24,0-2.25-1.01-2.25-2.25V4.62c0-1.24,1.01-2.25,2.25-2.25H23.22c1.24,0,2.25,1.01,2.25,2.25V25.38c0,1.24-1.01,2.25-2.25,2.25ZM6.78,3.87c-.41,0-.75,.34-.75,.75V25.38c0,.41,.34,.75,.75,.75H23.22c.41,0,.75-.34,.75-.75V4.62c0-.41-.34-.75-.75-.75H6.78Z"/><g><g><path d="M8.99,11.06h0c-.2,0-.39-.08-.53-.22l-1.42-1.42,1.06-1.06,.88,.89,2.74-2.74,1.06,1.06-3.27,3.27c-.14,.14-.33,.22-.53,.22Z"/><rect x="14.07" y="8.38" width="8.35" height="1.5"/></g><g><path d="M8.99,16.99c-.19,0-.38-.07-.53-.22l-1.42-1.42,1.06-1.06,.88,.88,2.74-2.74,1.06,1.06-3.27,3.27c-.15,.15-.34,.22-.53,.22Z"/><rect x="14.07" y="14.31" width="8.35" height="1.5"/></g><g><path d="M8.99,22.92c-.19,0-.38-.07-.53-.22l-1.42-1.42,1.06-1.06,.88,.88,2.74-2.74,1.06,1.06-3.27,3.27c-.15,.15-.34,.22-.53,.22Z"/><rect x="14.07" y="20.24" width="8.35" height="1.5"/></g></g></svg>

After

Width:  |  Height:  |  Size: 969 B

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg id="a" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30"><path d="M12.5,19.79c-.13,0-.26-.03-.38-.1-.23-.13-.38-.38-.38-.65V10.96c0-.27,.14-.52,.38-.65,.23-.13,.52-.13,.75,0l7,4.04c.23,.13,.38,.38,.38,.65s-.14,.52-.38,.65l-7,4.04c-.12,.07-.25,.1-.38,.1Zm.75-7.53v5.49l4.75-2.74-4.75-2.74Z"/><path d="M25.87,24.55H4.13c-1.24,0-2.25-1.01-2.25-2.25V7.7c0-1.24,1.01-2.25,2.25-2.25H25.87c1.24,0,2.25,1.01,2.25,2.25v14.6c0,1.24-1.01,2.25-2.25,2.25ZM4.13,6.95c-.41,0-.75,.34-.75,.75v14.6c0,.41,.34,.75,.75,.75H25.87c.41,0,.75-.34,.75-.75V7.7c0-.41-.34-.75-.75-.75H4.13Z"/></svg>

After

Width:  |  Height:  |  Size: 619 B

View File

@ -1 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?><svg id="a" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30"><rect x="9.12" y="8.49" width="15.36" height="1.5"/><rect x="5.52" y="8.49" width="1.5" height="1.5"/><rect x="9.12" y="14.25" width="15.36" height="1.5"/><rect x="5.52" y="14.25" width="1.5" height="1.5"/><rect x="9.12" y="20.01" width="15.36" height="1.5"/><rect x="5.52" y="20.01" width="1.5" height="1.5"/></svg> <?xml version="1.0" encoding="UTF-8"?>
<svg id="a" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30">
<rect x="9.12" y="8.49" width="15.36" height="1.5"/>
<rect x="5.52" y="8.49" width="1.5" height="1.5"/>
<rect x="9.12" y="14.25" width="15.36" height="1.5"/>
<rect x="5.52" y="14.25" width="1.5" height="1.5"/>
<rect x="9.12" y="20.01" width="15.36" height="1.5"/>
<rect x="5.52" y="20.01" width="1.5" height="1.5"/>
</svg>

Before

Width:  |  Height:  |  Size: 421 B

After

Width:  |  Height:  |  Size: 454 B

View File

@ -1 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?><svg id="a" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30"><path d="M9.32,28.18l-1.18-1.18,2.16-2.16c.84-.85,1.99-1.32,3.18-1.32,0,0,.01,0,.02,0,1.28,0,2.51-.51,3.42-1.42l8.94-8.94c.33-.32,.33-.85,.01-1.18-.32-.33-.85-.33-1.18-.01l-3.55,3.55c-.32,.33-.85,.34-1.18,.02s-.34-.85-.02-1.18l.02-.02,3.53-3.54,.02-.02,1.16-1.16c.33-.32,.33-.85,0-1.18h0c-.33-.32-.85-.32-1.18,0l-4.72,4.71c-.32,.33-.85,.34-1.18,.02s-.34-.85-.02-1.18l.02-.02,4.71-4.71h0l1.18-1.18c.33-.32,.34-.85,.02-1.18s-.85-.34-1.18-.02l-.02,.02-1.14,1.13-.04,.04-4.72,4.71c-.34,.31-.86,.3-1.18-.04-.3-.32-.3-.82,0-1.14l4.74-4.74c.32-.33,.31-.86-.02-1.18-.33-.32-.86-.31-1.18,.02l-7.66,7.66c-.33,.32-.85,.32-1.18,0-.13-.13-.22-.31-.24-.5l-.38-3.36c-.03-.44-.37-.81-.81-.87-.44-.03-.84,.27-.94,.7l-1.43,7.17c-.25,1.26-.07,2.56,.49,3.71,.16,.32,.09,.7-.16,.96l-3.1,3.1-1.18-1.18,2.69-2.7c-.53-1.34-.67-2.81-.39-4.22l1.43-7.17c.26-1.26,1.41-2.13,2.68-2.04,1.25,.11,2.23,1.1,2.35,2.35l.18,1.63,6.43-6.43c.47-.47,1.1-.73,1.77-.73h0c1,0,1.9,.59,2.29,1.51,1.2-.69,2.72-.27,3.41,.92,.44,.77,.44,1.72,0,2.49,1.27,.55,1.85,2.03,1.3,3.29-.04,.08-.08,.16-.12,.24,1.27,.55,1.85,2.01,1.31,3.28-.13,.29-.31,.56-.53,.78l-8.94,8.94c-1.21,1.22-2.87,1.91-4.59,1.9,0,0-.01,0-.02,0-.75,0-1.47,.3-2,.83l-2.16,2.16Z"/></svg> <?xml version="1.0" encoding="UTF-8"?>
<svg id="a" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30">
<path d="M9.32,28.18l-1.18-1.18,2.16-2.16c.84-.85,1.99-1.32,3.18-1.32,0,0,.01,0,.02,0,1.28,0,2.51-.51,3.42-1.42l8.94-8.94c.33-.32,.33-.85,.01-1.18-.32-.33-.85-.33-1.18-.01l-3.55,3.55c-.32,.33-.85,.34-1.18,.02s-.34-.85-.02-1.18l.02-.02,3.53-3.54,.02-.02,1.16-1.16c.33-.32,.33-.85,0-1.18h0c-.33-.32-.85-.32-1.18,0l-4.72,4.71c-.32,.33-.85,.34-1.18,.02s-.34-.85-.02-1.18l.02-.02,4.71-4.71h0l1.18-1.18c.33-.32,.34-.85,.02-1.18s-.85-.34-1.18-.02l-.02,.02-1.14,1.13-.04,.04-4.72,4.71c-.34,.31-.86,.3-1.18-.04-.3-.32-.3-.82,0-1.14l4.74-4.74c.32-.33,.31-.86-.02-1.18-.33-.32-.86-.31-1.18,.02l-7.66,7.66c-.33,.32-.85,.32-1.18,0-.13-.13-.22-.31-.24-.5l-.38-3.36c-.03-.44-.37-.81-.81-.87-.44-.03-.84,.27-.94,.7l-1.43,7.17c-.25,1.26-.07,2.56,.49,3.71,.16,.32,.09,.7-.16,.96l-3.1,3.1-1.18-1.18,2.69-2.7c-.53-1.34-.67-2.81-.39-4.22l1.43-7.17c.26-1.26,1.41-2.13,2.68-2.04,1.25,.11,2.23,1.1,2.35,2.35l.18,1.63,6.43-6.43c.47-.47,1.1-.73,1.77-.73h0c1,0,1.9,.59,2.29,1.51,1.2-.69,2.72-.27,3.41,.92,.44,.77,.44,1.72,0,2.49,1.27,.55,1.85,2.03,1.3,3.29-.04,.08-.08,.16-.12,.24,1.27,.55,1.85,2.01,1.31,3.28-.13,.29-.31,.56-.53,.78l-8.94,8.94c-1.21,1.22-2.87,1.91-4.59,1.9,0,0-.01,0-.02,0-.75,0-1.47,.3-2,.83l-2.16,2.16Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB