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

View File

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

View File

@ -1,15 +1,19 @@
import type { Circle } from '@/services/circle'
export type LearningContentType = 'assignment' | 'book' | 'document' |
'exercise' | 'media_library' | 'online_training' |
'resource' | 'test' | 'video';
export interface LearningContentBlock {
type: 'web-based-training' | 'competence' | 'exercise' | 'knowledge'
type: LearningContentType
value: {
description: string
}
id: string
}
export interface VideoBlock {
type: 'video';
export interface AssignmentBlock {
type: 'assignment';
value: {
description: string;
url: string;
@ -17,8 +21,8 @@ export interface VideoBlock {
id: string;
}
export interface PodcastBlock {
type: 'podcast';
export interface BookBlock {
type: 'book';
value: {
description: string;
url: string;
@ -35,6 +39,61 @@ export interface DocumentBlock {
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 {
type: 'goal';
value: string;
@ -58,7 +117,7 @@ export interface LearningWagtailPage {
export interface LearningContent extends LearningWagtailPage {
type: 'learnpath.LearningContent';
minutes: number;
contents: (LearningContentBlock | VideoBlock | PodcastBlock | DocumentBlock)[];
contents: (AssignmentBlock | BookBlock | DocumentBlock | ExerciseBlock | MediaLibraryBlock | OnlineTrainingBlock | ResourceBlock | TestBlock | VideoBlock)[];
parentCircle: Circle;
parentLearningSequence?: LearningSequence;
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,70 +1,67 @@
<script setup lang="ts">
import {reactive} from 'vue'
import {Listbox, ListboxButton, ListboxOption, ListboxOptions} from '@headlessui/vue'
import ItCheckbox from '@/components/ui/ItCheckbox.vue';
import ItDropdown from "@/components/ui/ItDropdown.vue";
import IconLogout from "@/components/icons/IconLogout.vue"
import IconSettings from "@/components/icons/IconSettings.vue"
import { reactive } from 'vue'
import { Listbox, ListboxButton, ListboxOption, ListboxOptions } from '@headlessui/vue'
import ItCheckbox from '@/components/ui/ItCheckbox.vue'
import ItDropdown from '@/components/ui/ItDropdown.vue'
import IconLogout from '@/components/icons/IconLogout.vue'
import IconSettings from '@/components/icons/IconSettings.vue'
const state = reactive({
checkboxValue: true,
dropdownValues: [
{id: 1, name: 'Wade Cooper'},
{id: 2, name: 'Arlene Mccoy'},
{id: 3, name: 'Devon Webb'},
{id: 4, name: 'Tom Cook'},
{id: 5, name: 'Tanya Fox'},
{id: 6, name: 'Hellen Schmidt'},
{id: 7, name: 'Caroline Schultz'},
{id: 8, name: 'Mason Heaney'},
{id: 9, name: 'Claudie Smitham'},
{id: 10, name: 'Emil Schaefer'},
{ id: 1, name: 'Wade Cooper' },
{ id: 2, name: 'Arlene Mccoy' },
{ id: 3, name: 'Devon Webb' },
{ id: 4, name: 'Tom Cook' },
{ id: 5, name: 'Tanya Fox' },
{ id: 6, name: 'Hellen Schmidt' },
{ id: 7, name: 'Caroline Schultz' },
{ id: 8, name: 'Mason Heaney' },
{ id: 9, name: 'Claudie Smitham' },
{ id: 10, name: 'Emil Schaefer' },
],
dropdownSelected: {id: 8},
dropdownSelected: { id: 8 },
})
const dropdownData = [
[
{
title: 'Option 1',
icon: IconLogout,
data: {}
[
{
title: 'Option 1',
icon: IconLogout,
data: {},
},
{
title: 'Option 2',
icon: null,
data: {
test: 12,
},
{
title: 'Option 2',
icon: null,
data: {
test: 12
}
}
],
[
{
title: 'Option 3',
icon: IconSettings,
data: {
amount: 34
}
},
],
[
{
title: 'Option 3',
icon: IconSettings,
data: {
amount: 34,
},
]
]
},
],
]
// 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
// noch nirgendwo verwendet werden.
const colors = ['blue', 'sky', 'green', 'red', 'orange', 'yellow', 'stone', 'gray', 'slate'];
const colorValues = [200, 300, 400, 500, 600, 700, 800, 900,];
const colors = ['blue', 'sky', 'green', 'red', 'orange', 'yellow', 'stone', 'gray', 'slate']
const colorValues = [200, 300, 400, 500, 600, 700, 800, 900]
function colorBgClass(color: string, value: number) {
return `bg-${color}-${value}`;
return `bg-${color}-${value}`
}
function log(data: any) {
console.log(data);
console.log(data)
}
</script>
<template>
@ -75,142 +72,190 @@ function log(data: any) {
<h2 class="heading-1">Icons</h2>
</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
&lt;it-icon-message/&gt; </p>
<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
&lt;it-icon-message/&gt;
</p>
<div class="mt-8 mb-8 flex flex-col gap-4 flex-wrap lg:flex-row">
<div class="inline-flex flex-col">
message
<it-icon-message class="it-icon"/>
<it-icon-message class="it-icon" />
</div>
<div class="inline-flex flex-col">
arrow-up
<it-icon-arrow-up/>
<it-icon-arrow-up />
</div>
<div class="inline-flex flex-col">
arrow-down
<it-icon-arrow-down/>
<it-icon-arrow-down />
</div>
<div class="inline-flex flex-col">
arrow-left
<it-icon-arrow-left/>
<it-icon-arrow-left />
</div>
<div class="inline-flex flex-col">
arrow-right
<it-icon-arrow-right/>
<it-icon-arrow-right />
</div>
<div class="inline-flex flex-col">
close
<it-icon-close/>
<it-icon-close />
</div>
<div class="inline-flex flex-col">
check
<it-icon-check/>
<it-icon-check />
</div>
<div class="inline-flex flex-col">
info
<it-icon-info/>
<it-icon-info />
</div>
<div class="inline-flex flex-col">
list
<it-icon-list/>
<it-icon-list />
</div>
<div class="inline-flex flex-col">
menu
<it-icon-menu/>
<it-icon-menu />
</div>
</div>
<div class="mt-8 mb-8 flex flex-col gap-4 flex-wrap lg:flex-row">
<div class="inline-flex flex-col">
ls-apply
<it-icon-ls-apply/>
<it-icon-ls-apply />
</div>
<div class="inline-flex flex-col">
ls-watch
<it-icon-ls-watch/>
<it-icon-ls-watch />
</div>
<div class="inline-flex flex-col">
ls-test
<it-icon-ls-test/>
<it-icon-ls-test />
</div>
<div class="inline-flex flex-col">
ls-practice
<it-icon-ls-practice/>
<it-icon-ls-practice />
</div>
<div class="inline-flex flex-col">
ls-network
<it-icon-ls-network/>
<it-icon-ls-network />
</div>
<div class="inline-flex flex-col">
ls-start
<it-icon-ls-start/>
<it-icon-ls-start />
</div>
<div class="inline-flex flex-col">
ls-end
<it-icon-ls-end/>
<it-icon-ls-end />
</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="inline-flex flex-col">
smiley-happy
<it-icon-smiley-happy/>
<it-icon-smiley-happy />
</div>
<div class="inline-flex flex-col">
smiley-thinking
<it-icon-smiley-thinking/>
<it-icon-smiley-thinking />
</div>
<div class="inline-flex flex-col">
smiley-neutral
<it-icon-smiley-neutral/>
<it-icon-smiley-neutral />
</div>
</div>
<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">
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 class="inline-flex flex-col text-blue-400">
ls-network big
<it-icon-ls-network class="w-16 h-16"/>
<it-icon-ls-network class="w-16 h-16" />
</div>
<div class="inline-flex flex-col text-red-500">
close small
<it-icon-close class="w-6 h-6"/>
<it-icon-close class="w-6 h-6" />
</div>
<div class="inline-flex flex-col text-white bg-blue-900">
vbv
<it-icon-vbv class="w-24 h-24"/>
<it-icon-vbv class="w-24 h-24" />
</div>
<div class="inline-flex flex-col">
vbv-pos
<it-icon-vbv-pos class="w-24 h-24"/>
<it-icon-vbv-pos class="w-24 h-24" />
</div>
</div>
<div class="border-b text-gray-700 pb-2 mt-8">
@ -219,10 +264,10 @@ function log(data: any) {
<table class="text-gray-700">
<tr class="h-12 md:h-18 lg:h-24">
<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 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">
<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>
@ -267,29 +312,24 @@ function log(data: any) {
</div>
<div class="flex flex-col gap-4 flex-wrap lg:flex-row content-center lg:justify-start mb-16">
<button type="button"
class="btn-primary inline-flex items-center p-3 rounded-full">
<button type="button" class="btn-primary inline-flex items-center p-3 rounded-full">
<it-icon-message class="h-5 w-5"></it-icon-message>
</button>
<button type="button"
class="btn-primary inline-flex items-center px-3 py-2">
<button type="button" 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>
Button text
</button>
<button type="button"
class="btn-primary inline-flex items-center px-3 py-2">
<button type="button" class="btn-primary inline-flex items-center px-3 py-2">
Button text
<it-icon-message class="ml-3 -mr-1 h-5 w-5"></it-icon-message>
</button>
<button type="button"
class="btn-text inline-flex items-center px-3 py-2">
<button type="button" 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>
Button text
</button>
</div>
<h2 class="mt-8 mb-8">Dropdown (Work-in-progress)</h2>
@ -297,29 +337,48 @@ function log(data: any) {
<Listbox as="div" v-model="state.dropdownSelected">
<div class="mt-1 relative w-128">
<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="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"/>
</span>
<it-icon-arrow-down class="h-5 w-5" aria-hidden="true" />
</span>
</ListboxButton>
<transition leave-active-class="transition ease-in duration-100" leave-from-class="opacity-100"
leave-to-class="opacity-0">
<transition
leave-active-class="transition ease-in duration-100"
leave-from-class="opacity-100"
leave-to-class="opacity-0"
>
<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">
<ListboxOption as="template" v-for="person in state.dropdownValues" :key="person.id" :value="person"
v-slot="{ active, selected }">
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 }"
>
<li
: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']">
{{ person.name }}
</span>
: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']">
{{ person.name }}
</span>
<span v-if="state.dropdownSelected"
: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
v-if="state.dropdownSelected"
: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>
</li>
</ListboxOption>
</ListboxOptions>
@ -336,16 +395,11 @@ function log(data: any) {
<h2 class="mt-8 mb-8">Dropdown</h2>
<div class="h-60">
<ItDropdown
:button-classes="['btn-primary']"
:list-items="dropdownData"
:align="'left'"
@select="log"
>Click Me</ItDropdown>
<ItDropdown :button-classes="['btn-primary']" :list-items="dropdownData" :align="'left'" @select="log"
>Click Me</ItDropdown
>
</div>
</main>
</template>
<style scoped>
</style>
<style scoped></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, \
LearningUnitQuestion
from vbv_lernwelt.learnpath.tests.learning_path_factories import LearningPathFactory, TopicFactory, CircleFactory, \
LearningSequenceFactory, LearningContentFactory, VideoBlockFactory, PodcastBlockFactory, CompetenceBlockFactory, \
ExerciseBlockFactory, DocumentBlockFactory, LearningUnitFactory, LearningUnitQuestionFactory
LearningSequenceFactory, LearningContentFactory, VideoBlockFactory, ResourceBlockFactory, \
ExerciseBlockFactory, DocumentBlockFactory, LearningUnitFactory, LearningUnitQuestionFactory, \
AssignmentBlockFactory, BookBlockFactory, MediaLibraryBlockFactory, OnlineTrainingBlockFactory, TestBlockFactory
def create_circle(title, learning_path):
@ -73,7 +74,7 @@ def create_circle_children(circle, title):
title='Ermittlung des Kundenbedarfs',
parent=circle,
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.',
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',
parent=circle,
minutes=30,
contents=[('competence', CompetenceBlockFactory())]
contents=[('exercise', ExerciseBlockFactory())]
)
LearningContentFactory(
@ -164,13 +165,13 @@ def create_circle_children(circle, title):
title='Motorfahrzeugversicherung',
parent=circle,
minutes=240,
contents=[('competence', CompetenceBlockFactory())]
contents=[('assignment', AssignmentBlockFactory())]
)
LearningContentFactory(
title='Nora kauft sich ein neues Auto',
parent=circle,
minutes=60,
contents=[('podcast', PodcastBlockFactory())]
contents=[('resource', ResourceBlockFactory())]
)
LearningContentFactory(
title='Ermittlung des Kundenbedarfs',
@ -194,13 +195,13 @@ def create_circle_children(circle, title):
title='3-Säulen-Prinzip',
parent=circle,
minutes=240,
contents=[('competence', CompetenceBlockFactory())]
contents=[('test', TestBlockFactory())]
)
LearningContentFactory(
title='Altersvorsorge',
parent=circle,
minutes=240,
contents=[('competence', CompetenceBlockFactory())]
contents=[('test', TestBlockFactory())]
)
LearningContentFactory(
title='AHV',
@ -224,7 +225,7 @@ def create_circle_children(circle, title):
title='Reiseversicherung',
parent=circle,
minutes=240,
contents=[('competence', CompetenceBlockFactory())]
contents=[('exercise', ExerciseBlockFactory())]
)
LearningContentFactory(
title='Sorgenfrei reisen',
@ -243,7 +244,7 @@ def create_circle_children(circle, title):
title='Privathaftpflicht',
parent=circle,
minutes=240,
contents=[('competence', CompetenceBlockFactory())]
contents=[('media_library', MediaLibraryBlockFactory())]
)
LearningContentFactory(
title='Zusatzversicherung',
@ -268,19 +269,19 @@ def create_circle_children(circle, title):
title='Hausrat',
parent=circle,
minutes=120,
contents=[('competence', CompetenceBlockFactory())]
contents=[('online_training', OnlineTrainingBlockFactory())]
)
LearningContentFactory(
title='Privathaftpflicht',
parent=circle,
minutes=60,
contents=[('competence', CompetenceBlockFactory())]
contents=[('exercise', ExerciseBlockFactory())]
)
LearningContentFactory(
title='Kind zieht von zu Hause wirklich aus',
parent=circle,
minutes=60,
contents=[('competence', CompetenceBlockFactory())]
contents=[('exercise', ExerciseBlockFactory())]
)
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',
parent=circle,
minutes=30,
contents=[('document', CompetenceBlockFactory())]
contents=[('test', TestBlockFactory())]
)
LearningContentFactory(
title='Test durchführen',
parent=circle,
minutes=30,
contents=[('document', CompetenceBlockFactory())]
contents=[('test', TestBlockFactory())]
)
LearningSequenceFactory(title='Vernetzen', parent=circle, icon='it-icon-ls-network')
@ -307,21 +308,21 @@ def create_circle_children(circle, title):
title='Online Training',
parent=circle,
minutes=60,
contents=[('document', CompetenceBlockFactory())]
contents=[('online_training', OnlineTrainingBlockFactory())]
)
LearningSequenceFactory(title='Beenden', parent=circle, icon='it-icon-ls-end')
LearningContentFactory(
title='Kompetenzprofil anschauen',
title='Mehr darüber erfahren',
parent=circle,
minutes=30,
contents=[('document', CompetenceBlockFactory())]
contents=[('book', BookBlockFactory())]
)
LearningContentFactory(
title='Circle "Analyse" abschliessen',
parent=circle,
minutes=30,
contents=[('document', CompetenceBlockFactory())]
contents=[('document', DocumentBlockFactory())]
)
@ -369,13 +370,13 @@ damit erfolgreich mit deinem Lernpfad starten kannst.
title='Kompetenzprofil anschauen',
parent=circle_basis,
minutes=30,
contents=[('document', CompetenceBlockFactory())]
contents=[('document', DocumentBlockFactory())]
)
LearningContentFactory(
title='Circle "Analyse" abschliessen',
parent=circle_basis,
minutes=30,
contents=[('document', CompetenceBlockFactory())]
contents=[('document', DocumentBlockFactory())]
)
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.fields import StreamField
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, \
CompetenceBlock, ExerciseBlock, DocumentBlock, KnowledgeBlock
from vbv_lernwelt.learnpath.models_learning_unit_content import VideoBlock, \
ExerciseBlock, DocumentBlock, AssignmentBlock, BookBlock, MediaLibraryBlock, \
OnlineTrainingBlock, ResourceBlock, TestBlock
from vbv_lernwelt.learnpath.serializer_helpers import get_it_serializer_class
@ -208,12 +209,14 @@ class LearningContent(Page):
content_blocks = [
('video', VideoBlock()),
('web_based_training', WebBasedTrainingBlock()),
('podcast', PodcastBlock()),
('competence', CompetenceBlock()),
('resource', ResourceBlock()),
('exercise', ExerciseBlock()),
('online_training', OnlineTrainingBlock()),
('media_library', MediaLibraryBlock()),
('document', DocumentBlock()),
('knowledge', KnowledgeBlock()),
('test', TestBlock()),
('book', BookBlock()),
('assignment', AssignmentBlock()),
]
contents = StreamField(

View File

@ -1,5 +1,60 @@
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):
# TODO: Possible video Types for the user, upload file, add URL
@ -7,51 +62,4 @@ class VideoBlock(blocks.StructBlock):
url = blocks.URLBlock()
class Meta:
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'
icon = 'media'

View File

@ -1,11 +1,11 @@
import wagtail_factories
from django.conf import settings
from wagtail.models import Site, Page
from vbv_lernwelt.core.admin import User
from vbv_lernwelt.learnpath.tests.learning_path_factories import LearningPathFactory, TopicFactory, CircleFactory, \
LearningSequenceFactory, LearningContentFactory, CompetenceBlockFactory, \
ExerciseBlockFactory, LearningUnitFactory, LearningUnitQuestionFactory
LearningSequenceFactory, LearningContentFactory, \
ExerciseBlockFactory, LearningUnitFactory, LearningUnitQuestionFactory, \
DocumentBlockFactory, TestBlockFactory, OnlineTrainingBlockFactory
def create_circle(title, learning_path):
@ -33,7 +33,7 @@ def create_circle_children(circle, title):
title=f'Einleitung Circle "{title}"',
parent=circle,
minutes=15,
contents=[('competence', CompetenceBlockFactory())]
contents=[('document', DocumentBlockFactory())]
)
LearningSequenceFactory(title='Beobachten', parent=circle, icon='it-icon-ls-watch')
@ -53,13 +53,16 @@ def create_circle_children(circle, title):
title='Ermittlung des Kundenbedarfs',
parent=circle,
minutes=30,
contents=[('competence', CompetenceBlockFactory())]
contents=[('online_training', OnlineTrainingBlockFactory(
description='In diesem Online-Training lernst du, wie du den Kundenbedarf ermittelst.',
url='',
))]
)
LearningContentFactory(
title='Kundenbedürfnisse erkennen',
parent=circle,
minutes=30,
contents=[('competence', CompetenceBlockFactory())]
contents=[('test', TestBlockFactory())]
)
LearningContentFactory(
title='Was braucht eine Familie?',
@ -79,7 +82,7 @@ def create_circle_children(circle, title):
title='Reiseversicherung',
parent=circle,
minutes=240,
contents=[('competence', CompetenceBlockFactory())]
contents=[('exercise', ExerciseBlockFactory())]
)
LearningContentFactory(
title='Sorgenfrei reisen',
@ -94,13 +97,13 @@ def create_circle_children(circle, title):
title='Kompetenzprofil anschauen',
parent=circle,
minutes=30,
contents=[('document', CompetenceBlockFactory())]
contents=[('document', DocumentBlockFactory())]
)
LearningContentFactory(
title='Circle "Analyse" abschliessen',
parent=circle,
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"',
parent=circle_basis,
minutes=15,
contents=[('competence', CompetenceBlockFactory())]
contents=[('document', DocumentBlockFactory())]
)
LearningSequenceFactory(title='Beenden', parent=circle_basis, icon='it-icon-ls-end')
LearningContentFactory(
title='Kompetenzprofil anschauen',
parent=circle_basis,
minutes=30,
contents=[('document', CompetenceBlockFactory())]
contents=[('document', DocumentBlockFactory())]
)
LearningContentFactory(
title='Circle "Analyse" abschliessen',
parent=circle_basis,
minutes=30,
contents=[('document', CompetenceBlockFactory())]
contents=[('document', DocumentBlockFactory())]
)
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, \
LearningUnitQuestion
from vbv_lernwelt.learnpath.models_learning_unit_content import VideoBlock, WebBasedTrainingBlock, PodcastBlock, \
CompetenceBlock, ExerciseBlock, DocumentBlock, KnowledgeBlock
from vbv_lernwelt.learnpath.models_learning_unit_content import VideoBlock, OnlineTrainingBlock, \
ExerciseBlock, DocumentBlock, ResourceBlock, TestBlock, BookBlock, MediaLibraryBlock, AssignmentBlock
class LearningPathFactory(wagtail_factories.PageFactory):
@ -48,7 +48,6 @@ class LearningUnitQuestionFactory(wagtail_factories.PageFactory):
class Meta:
model = LearningUnitQuestion
class LearningContentFactory(wagtail_factories.PageFactory):
title = 'Lerninhalt'
@ -63,37 +62,17 @@ class VideoBlockFactory(wagtail_factories.StructBlockFactory):
class Meta:
model = VideoBlock
class WebBasedTrainingBlockFactory(wagtail_factories.StructBlockFactory):
url = "/static/media/web_based_trainings/rise_cmi5_test_export/scormcontent/index.html"
description = "Beispiel Rise Modul"
class AssignmentBlockFactory(wagtail_factories.StructBlockFactory):
description = "Beispiel Auftrag"
class Meta:
model = WebBasedTrainingBlock
model = AssignmentBlock
class PodcastBlockFactory(wagtail_factories.StructBlockFactory):
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 BookBlockFactory(wagtail_factories.StructBlockFactory):
description = "Beispiel Buch"
class Meta:
model = PodcastBlock
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
model = BookBlock
class DocumentBlockFactory(wagtail_factories.StructBlockFactory):
description = "Beispiel Dokument"
@ -101,9 +80,33 @@ class DocumentBlockFactory(wagtail_factories.StructBlockFactory):
class Meta:
model = DocumentBlock
class KnowledgeBlockFactory(wagtail_factories.StructBlockFactory):
description = "Beispiel Wissen"
class ExerciseBlockFactory(wagtail_factories.StructBlockFactory):
description = "Beispiel Übung"
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