WIP CreatePage; BoardView/BoardEntryView implementation

This commit is contained in:
Baer 2024-08-28 20:10:00 +02:00
parent d2a0551ddd
commit c5d6075c01
15 changed files with 440 additions and 69 deletions

View File

@ -52,6 +52,9 @@ $breadcrumb-divider: quote(">");
@import "bootstrap/scss/variables";
@import "bootstrap/scss/variables-dark";
$form-file-button-bg: var(--#{$prefix}secondary-bg);
$form-file-button-hover-bg: var(--#{$prefix}tertiary-bg);
/* Bootstrap Color Map adjustments */
$custom-colors: (

View File

@ -1,25 +1,97 @@
<script setup lang="ts">
import type { BoardEntry } from '@/models/board/BoardEntry';
import { computed } from 'vue';
const QUESTION_TYPE_SIMPLE_TEXT_ID = 1;
const QUESTION_TYPE_IMAGE_ID = 2;
const props = defineProps<{
boardEntry: BoardEntry,
selectedQuestionIndex: number,
isAnswerShown: boolean,
}>();
const emit = defineEmits<{
questionSelected: [questionIndex: number],
}>();
const question = computed( () => {
return props.boardEntry.questions[props.selectedQuestionIndex ?? 0];
});
function selectQuestionIndex( qIndex: number ) {
emit( "questionSelected", qIndex );
}
</script>
<template>
<div class="mx-3 h-100 d-flex flex-column">
<div class="row">
<div class="col text-center p-3">
<h2>
{{ boardEntry.name }}
</h2>
<div class="h-100 d-flex flex-column">
<div class="row h-100">
<div class="col h-100 mx-3 overflow-y-auto">
<div class="ratio ratio-16x9">
<div class="w-100 h-100 d-flex justify-content-center align-items-center">
<span v-if="boardEntry.questions.length === 0" class="fs-1">
No Question to show
</span>
<span v-else-if="question.questionType.id === QUESTION_TYPE_SIMPLE_TEXT_ID" class="text-center preserve-breaks" :style="`font-size: ${question.fontScaling}em`">
{{ question.text }}
</span>
<template v-else-if="question.questionType.id === QUESTION_TYPE_IMAGE_ID">
<div class="d-flex flex-column justify-content-center align-items-center h-100 w-100">
<span class="text-center preserve-breaks" :style="`font-size: ${question.fontScaling}em`">
{{ question.text }}
</span>
<div class="h-75 w-100 d-flex justify-content-center align-items-center">
<img
v-if="question.image"
:src="question.image"
alt="User uploaded - No caption available"
class="h-100 w-100 object-contain"
>
</div>
</div>
</template>
<!-- Category Name -->
<div class="position-absolute top-0 start-0 mt-2">
<span class="fs-2">
{{ boardEntry.category.name }}
</span>
</div>
<!-- Points -->
<div class="position-absolute bottom-0 end-0">
<span class="fs-2">
{{ boardEntry.points }}
</span>
</div>
<!-- Answer -->
<div v-if="isAnswerShown" class="position-absolute bottom-0 start-50 translate-middle-x mb-2">
<div class="bg-primary p-2 rounded bg-opacity-50 fs-4 text-center">
Answer:<br>{{ boardEntry.answer.text }}
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row h-100">
<div class="col">
Entry
</div>
<div v-if=" props.boardEntry.questions.length > 1 " class="position-absolute bottom-0 start-0 mb-3 ms-3">
<template v-for="( question, questionIndex) in props.boardEntry.questions" :key="question.id">
<button class="btn me-2"
:class="[
{ 'btn-primary': props.selectedQuestionIndex === questionIndex },
{ 'btn-outline-primary': props.selectedQuestionIndex !== questionIndex }
]"
:disabled="props.selectedQuestionIndex === questionIndex"
@click="selectQuestionIndex( questionIndex )">
{{ questionIndex + 1 }}
</button>
</template>
</div>
</div>
</template>
</template>
<style lang="css" scoped>
.object-contain{
object-fit: contain;
}
</style>

View File

@ -4,16 +4,19 @@ import type { Board } from '@/models/board/Board';
import EditCategoryPanel from '@/components/blocks/EditCategoryPanel.vue';
import EditBoardPanel from '@/components/blocks/EditBoardPanel.vue';
import EditBoardEntryPanel from '@/components/blocks/EditBoardEntryPanel.vue';
import EditQuestionPanel from './EditQuestionPanel.vue';
const props = defineProps<{
categoryIndex: number | null,
boardEntryIndex: number | null,
questionIndex: number | null,
}>()
const emit = defineEmits<{
editBoard: [],
editCategory: [cIndex: number],
editBoardEntry: [cIndex: number, bEIndex: number],
editQuestion: [cIndex: number, bEIndex: number, qIndex: number],
}>()
const board = defineModel<Board>( { required: true } );
@ -27,14 +30,44 @@ function editCategory(cIndex: number){
function editBoardEntry(cIndex: number, bEIndex: number){
emit("editBoardEntry", cIndex, bEIndex);
}
function editQuestion(cIndex: number, bEIndex: number, qIndex: number){
emit("editQuestion", cIndex, bEIndex, qIndex);
}
</script>
<template>
<div class="d-flex flex-column h-100">
<div class="flex-grow-1 overflow-y-auto p-2">
<EditBoardPanel v-model="board" v-if="props.categoryIndex === null && props.boardEntryIndex === null" @editCategory="editCategory" />
<EditCategoryPanel v-model="board" :categoryIndex="props.categoryIndex" v-else-if="props.categoryIndex !== null && props.boardEntryIndex === null" @editBoard="editBoard" @editBoardEntry="editBoardEntry"/>
<EditBoardEntryPanel v-model="board" :categoryIndex="props.categoryIndex" :boardEntryIndex="props.boardEntryIndex" v-else-if="props.categoryIndex !== null && props.boardEntryIndex !== null" @editCategory="editCategory" @editBoard="editBoard" />
<EditBoardPanel
v-if="props.categoryIndex === null && props.boardEntryIndex === null && props.questionIndex === null"
v-model="board"
@editCategory="editCategory"
/>
<EditCategoryPanel
v-else-if="props.categoryIndex !== null && props.boardEntryIndex === null && props.questionIndex === null"
v-model="board"
:categoryIndex="props.categoryIndex"
@editBoard="editBoard"
@editBoardEntry="editBoardEntry"
/>
<EditBoardEntryPanel
v-else-if="props.categoryIndex !== null && props.boardEntryIndex !== null && props.questionIndex === null"
v-model="board" :categoryIndex="props.categoryIndex"
:boardEntryIndex="props.boardEntryIndex"
@editQuestion="editQuestion"
@editCategory="editCategory"
@editBoard="editBoard"
/>
<EditQuestionPanel
v-else-if="props.categoryIndex !== null && props.boardEntryIndex !== null && props.questionIndex !== null"
v-model="board"
:categoryIndex="props.categoryIndex"
:boardEntryIndex="props.boardEntryIndex"
:questionIndex="props.questionIndex"
@editBoardEntry="editBoardEntry"
@editCategory="editCategory"
@editBoard="editBoard"
/>
</div>
<div class="border-top border-2 border-primary p-2">
<div class="d-flex align-items-center">

View File

@ -1,10 +1,12 @@
<script setup lang="ts">
import type { Board } from '@/models/board/Board';
import { computed, ref } from 'vue';
import { computed, inject, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
import { BoardEntry } from '@/models/board/BoardEntry';
import { Answer } from '@/models/board/Answer';
import { VueDraggable } from 'vue-draggable-plus';
import type { Board } from '@/models/board/Board';
import { Question } from '@/models/board/Question';
import { QuestionType } from '@/models/board/QuestionType';
import { questionTypesKey } from '@/services/UtilService';
const { t } = useI18n();
@ -14,46 +16,48 @@ const props = defineProps<{
categoryIndex: number,
boardEntryIndex: number,
}>();
const questionTypes = inject(questionTypesKey);
const emit = defineEmits<{
editBoard: [],
editCategory: [categoryIndex: number],
editQuestion: [categoryIndex: number, boardEntryIndex: number, questionIndex: number],
}>()
const boardEntry = computed( () => {
return board.value.categories[props.categoryIndex].boardEntries[props.boardEntryIndex];
})
});
const newBoardEntryName = ref( '' );
function addBoardEntry() {
if( board.value.categories[props.categoryIndex].boardEntries.length >= 10 ) {
const newQuestionText = ref( '' );
const newQuestionType = ref<QuestionType | null>( (questionTypes ?? [null])[0] );
function addQuestion() {
if( boardEntry.value.questions.length >= 10 || newQuestionType.value === null) {
return;
}
const answer = new Answer('', undefined);
const newBoardEntry = new BoardEntry( newBoardEntryName.value, 0, board.value.categories[props.categoryIndex], answer, [] );
board.value.categories[props.categoryIndex].boardEntries.push( newBoardEntry );
const newQuestion = new Question(newQuestionText.value, newQuestionType.value, boardEntry.value );
boardEntry.value.questions.push( newQuestion );
}
function deleteBoardEntry( index: number ) {
board.value.categories[props.categoryIndex].boardEntries.splice( index, 1 );
function deleteQuestion( index: number ) {
boardEntry.value.questions.splice( index, 1 );
}
function moveBoardEntryUp( index: number ) {
if( index === 0 || board.value.categories[props.categoryIndex].boardEntries.length <= 1 ) {
function moveQuestionUp( index: number ) {
if( index === 0 || boardEntry.value.questions.length <= 1 ) {
return;
}
const tmp = board.value.categories[props.categoryIndex].boardEntries[index];
board.value.categories[props.categoryIndex].boardEntries[index] = board.value.categories[props.categoryIndex].boardEntries[index - 1];
board.value.categories[props.categoryIndex].boardEntries[index - 1] = tmp;
const tmp = boardEntry.value.questions[index];
boardEntry.value.questions[index] = boardEntry.value.questions[index - 1];
boardEntry.value.questions[index - 1] = tmp;
}
function moveBoardEntryDown( index: number ) {
if( index === board.value.categories[props.categoryIndex].boardEntries.length - 1 || board.value.categories[props.categoryIndex].boardEntries.length <= 1 ) {
function moveQuestionDown( index: number ) {
if( index === boardEntry.value.questions.length - 1 || boardEntry.value.questions.length <= 1 ) {
return;
}
const tmp = board.value.categories[props.categoryIndex].boardEntries[index];
board.value.categories[props.categoryIndex].boardEntries[index] = board.value.categories[props.categoryIndex].boardEntries[index + 1];
board.value.categories[props.categoryIndex].boardEntries[index + 1] = tmp;
const tmp = boardEntry.value.questions[index];
boardEntry.value.questions[index] = boardEntry.value.questions[index + 1];
boardEntry.value.questions[index + 1] = tmp;
}
function openBoard() {
@ -62,6 +66,9 @@ function openBoard() {
function openCategory(categoryIndex: number) {
emit("editCategory", categoryIndex);
}
function openQuestion(categoryIndex: number, boardEntryIndex: number, questionIndex: number) {
emit("editQuestion", categoryIndex, boardEntryIndex, questionIndex);
}
</script>
<template>
@ -70,7 +77,7 @@ function openCategory(categoryIndex: number) {
<div class="row">
<div class="col">
<div class="d-flex align-items-center mb-2 overflow-x-auto pb-2">
<button class="btn btn-sm btn-outline-primary" :title="t('board.category.back')" @click="openCategory(props.categoryIndex)">
<button class="btn btn-sm btn-outline-primary" :title="t('common.back')" @click="openCategory(props.categoryIndex)">
<FontAwesomeIcon :icon="['fas', 'angle-left']"/>
</button>
<nav class="flex-grow-1 ms-2" aria-label="breadcrumb">
@ -106,7 +113,81 @@ function openCategory(categoryIndex: number) {
</div>
<div class="row mt-3">
<div class="col">
Questions
<h4>{{ t( "board.question.label", 2 ) }}</h4>
<template v-if=" boardEntry.questions.length === 0 ">
<p>
{{ t( "board.question.label", 0 ) }}
</p>
</template>
<template v-else>
<VueDraggable v-model="board.categories[props.categoryIndex].boardEntries" item-key="id" :animation="150" ghost-class="draggable-ghost"
tag="ul" class="list-group" handle=".drag-handle">
<template v-for="(question, questionIndex) of boardEntry.questions" :key="question.id">
<li class="list-group-item bg-body-secondary p-0">
<div class="d-flex justify-content-between w-100">
<div class="flex-grow-1 d-flex align-items-center text-truncate">
<div
class="drag-handle h-100 d-flex justify-content-center align-items-center cursor-move border-end border-1 bg-primary bg-opacity-10">
<FontAwesomeIcon :icon="['fas', 'grip-lines']" class="px-2" />
</div>
<div class="text-truncate">
<span class="ms-2">
{{ question.questionType.title }}
<span class="fw-light">
({{ question.text.length === 0 ? 'No Text yet' : question.text }})
</span>
</span>
</div>
</div>
<div class="d-flex">
<button class="btn btn-primary rounded-0" @click="openQuestion( props.categoryIndex, props.boardEntryIndex, questionIndex )">
<FontAwesomeIcon :icon="['fas', 'edit']" size="sm" />
</button>
<div class="d-flex flex-column justify-content-center align-items-center h-100" role="group"
aria-label="Vertical button group">
<button class="btn btn-primary rounded-0 py-0 lh-sm" @click="moveQuestionUp( questionIndex )"
:disabled="questionIndex === 0">
<FontAwesomeIcon :icon="['fas', 'angle-up']" size="xs" />
</button>
<button class="btn btn-primary rounded-0 py-0 lh-sm" @click="moveQuestionDown( questionIndex )"
:disabled="questionIndex === boardEntry.questions.length - 1">
<FontAwesomeIcon :icon="['fas', 'angle-down']" size="xs" />
</button>
</div>
<button class="btn btn-danger rounded-start-0 rounded-0"
:class="[{ 'rounded-bottom-end': questionIndex === boardEntry.questions.length - 1 }, { 'rounded-top-end': questionIndex === 0 }]"
@click="deleteQuestion( questionIndex )">
<FontAwesomeIcon :icon="['fas', 'trash']" size="sm" />
</button>
</div>
</div>
</li>
</template>
</VueDraggable>
</template>
<label class="mt-2" for="new-category-name">{{ t( "board.question.add" ) }}</label>
<div class="row mb-2">
<div class="col">
<select id="type-for-new-question" v-model="newQuestionType" class="form-select">
<template v-for="questionType in questionTypes" :key="questionType.id">
<option :value="questionType" :title="questionType.description">{{ questionType.title }}</option>
</template>
</select>
</div>
<div class="col-auto">
<button class="btn btn-primary" @click="addQuestion">
<FontAwesomeIcon :icon="['fas', 'plus']" />
</button>
</div>
</div>
<div class="row">
<div class="col">
<h4>{{ t('board.answer.label', 2) }}</h4>
<label for="answer-text">{{ t( 'board.answer.text' ) }}</label>
<textarea id="answer-text" v-model="boardEntry.answer.text" class="form-control mb-2"
:placeholder="t( 'board.answer.text' )"></textarea>
</div>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,129 @@
<script setup lang="ts">
import type { Board } from '@/models/board/Board';
import { computed, inject, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
import { questionTypesKey } from '@/services/UtilService';
const QUESTION_TYPE_IMAGE_ID = 2;
const { t } = useI18n();
const board = defineModel<Board>( { required: true } );
const props = defineProps<{
categoryIndex: number,
boardEntryIndex: number,
questionIndex: number;
}>();
const questionTypes = inject( questionTypesKey );
const emit = defineEmits<{
editBoard: [],
editCategory: [categoryIndex: number],
editBoardEntry: [categoryIndex: number, boardEntryIndex: number],
}>();
const question = computed( () => {
return board.value.categories[props.categoryIndex].boardEntries[props.boardEntryIndex].questions[props.questionIndex];
} );
function openBoard() {
emit( "editBoard" );
}
function openCategory( categoryIndex: number ) {
emit( "editCategory", categoryIndex );
}
function openBoardEntry( categoryIndex: number, boardEntryIndex: number ) {
emit( "editBoardEntry", categoryIndex, boardEntryIndex );
}
const imageInput = ref<File | null>( null );
function newImageUploaded( event: Event ) {
const element = event.currentTarget as HTMLInputElement;
let files = element.files;
if( files === null || files.length === 0 ) {
return;
}
imageInput.value = files[0];
question.value.image = URL.createObjectURL(files[0]);
}
</script>
<template>
<div class="d-flex flex-column h-100">
<div class="flex-grow-1 px-2">
<div class="row">
<div class="col">
<div class="d-flex align-items-center mb-2 overflow-x-auto pb-2">
<button class="btn btn-sm btn-outline-primary" :title="t( 'common.back' )"
@click="openBoardEntry( props.categoryIndex, props.boardEntryIndex )">
<FontAwesomeIcon :icon="['fas', 'angle-left']" />
</button>
<nav class="flex-grow-1 ms-2" aria-label="breadcrumb">
<ol class="breadcrumb mb-0 flex-nowrap">
<li class="breadcrumb-item text-truncate">
<a href="#" @click="openBoard">
{{ board.name }}
</a>
</li>
<li class="breadcrumb-item text-truncate">
<a href="#" @click="openCategory( props.categoryIndex )">
{{ board.categories[props.categoryIndex].name }}
</a>
</li>
<li class="breadcrumb-item text-truncate">
<a href="#" @click="openBoardEntry( props.categoryIndex, props.boardEntryIndex )">
{{ board.categories[props.categoryIndex].boardEntries[props.boardEntryIndex].name }}
</a>
</li>
<li class="breadcrumb-item active text-truncate" style="max-width: 6em;" aria-current="page">
{{ question.text.length !== 0 ? question.text : question.questionType.title }}
</li>
</ol>
</nav>
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="d-flex border-bottom border-3 border-primary align-items-center mb-2">
<h2 class="flex-grow-1 ms-2">{{ t( "board.question.infos" ) }}</h2>
</div>
<label for="question-text">{{ t( 'board.question.text' ) }}</label>
<textarea id="question-text" v-model="question.text" class="form-control mb-2"
:placeholder="t( 'board.question.text' )"></textarea>
<label for="question-font-size-input">{{ t( 'board.question.fontsize' ) }}</label>
<input type="number" id="question-font-size-input" v-model="question.fontScaling" class="form-control mb-2">
<label for="board-entry-points">{{ t( 'board.question.type' ) }}</label>
<select id="question-type" v-model="question.questionType" class="form-select mb-2" aria-label="Question Type">
<template v-for=" questionType in questionTypes " :key="questionType.id">
<option :value="questionType" :title="questionType.description">{{ questionType.title }}</option>
</template>
</select>
<template v-if=" question.questionType.id === QUESTION_TYPE_IMAGE_ID ">
<label for="question-image-input">{{ t( 'board.question.upload.image' ) }}</label>
<input
id="question-image-input"
type="file"
class="form-control mb-2"
@change="newImageUploaded"
accept="image/png, image/jpeg"
>
</template>
</div>
</div>
</div>
</div>
</template>
<style lang="css" scoped>
.draggable-ghost {
opacity: .75;
}
</style>

View File

@ -67,7 +67,7 @@ userStore.userCheckPromise
<nav ref="navbar" id="navbar-main" class="navbar navbar-expand-lg bg-dark-accented">
<div class="container px-5">
<div class="position-absolute start-0 top-50 translate-middle-y d-flex ms-3 gap-3">
<div class="position-absolute start-0 top-50 translate-middle-y d-flex ms-3 gap-3 z-2">
<ThemeChanger />
<LocaleChanger />
</div>

View File

@ -1,8 +1,8 @@
<script setup lang="ts">
import { computed, inject, ref, type Ref } from 'vue';
import { computed, inject, provide, ref, type Ref } from 'vue';
import { useI18n } from 'vue-i18n';
import { navbarKey } from '@/services/UtilService';
import { navbarKey, questionTypesKey } from '@/services/UtilService';
import { Board } from '@/models/board/Board';
import type NavBar from '@/components/blocks/NavBar.vue';
@ -12,51 +12,89 @@ import { Category } from '@/models/board/Category';
import BoardEntryView from '../blocks/BoardEntryView.vue';
import { BoardEntry } from '@/models/board/BoardEntry';
import { Answer } from '@/models/board/Answer';
import { QuestionType } from '@/models/board/QuestionType';
const { t } = useI18n();
const navbar = inject<Ref<InstanceType<typeof NavBar> | null>>(navbarKey);
const navbar = inject<Ref<InstanceType<typeof NavBar> | null>>( navbarKey );
const navbarHeight = computed( () => {
return navbar?.value?.navElement?.clientHeight;
});
} );
const restHeight = computed( () => {
return { height: `calc(100vh - ${navbarHeight.value}px)`};
})
return { height: `calc(100vh - ${navbarHeight.value}px)` };
} );
const board = ref<Board>(new Board("New Board"));
const board1 = ref<Board>(new Board("New Board", [new Category("Test1", "", board.value as Board),new Category("Test2", "", board.value as Board)]));
const answer = new Answer('', undefined);
const newBoardEntry = new BoardEntry( "Test Entry 1", 0, board1.value.categories[0] as Category, answer, [] );
const board = ref<Board>( new Board( "New Board" ) );
const board1 = ref<Board>( new Board( "New Board", [new Category( "Test1", "", board.value as Board ), new Category( "Test2", "", board.value as Board )] ) );
const answer = new Answer( '', undefined );
const newBoardEntry = new BoardEntry( "Test Entry 1", board1.value.categories[0] as Category, answer, [] );
board1.value.categories[0].boardEntries.push( newBoardEntry );
const categoryIndex = ref<number | null>(null);
const boardEntryIndex = ref<number | null>(null);
const categoryIndex = ref<number | null>( null );
const boardEntryIndex = ref<number | null>( null );
const questionIndex = ref<number | null>( null );
function showBoardEntry(cIndex: number, bEIndex: number){
function showQuestion( cIndex: number, bEIndex: number, qIndex: number ) {
categoryIndex.value = cIndex;
boardEntryIndex.value = bEIndex;
questionIndex.value = qIndex;
}
function showCategory(cIndex: number){
function showBoardEntry( cIndex: number, bEIndex: number ) {
categoryIndex.value = cIndex;
boardEntryIndex.value = bEIndex;
questionIndex.value = null;
}
function showCategory( cIndex: number ) {
categoryIndex.value = cIndex;
boardEntryIndex.value = null;
questionIndex.value = null;
}
function showBoard(){
function showBoard() {
categoryIndex.value = null;
boardEntryIndex.value = null;
questionIndex.value = null;
}
const questionTypes = [
new QuestionType("Simple Text", "A simple question with just text", true, 1),
new QuestionType("Image Question", "A question with text and an image", true, 2),
new QuestionType("Audio Question", "A question with text and some audio", true, 3),
];
provide(questionTypesKey, questionTypes);
</script>
<template>
<div :style="restHeight">
<div class="row h-100">
<div class="col-9 pe-0">
<BoardEntryView v-if="categoryIndex !== null && boardEntryIndex !== null" :boardEntry="(board1.categories[categoryIndex].boardEntries[boardEntryIndex] as BoardEntry)" />
<BoardView v-else :board="(board1 as Board)" @categorySelected="showCategory" @boardEntrySelected="showBoardEntry" />
<div class="col-9 h-100 pe-0">
<BoardEntryView
v-if=" categoryIndex !== null && boardEntryIndex !== null "
:boardEntry="( board1.categories[categoryIndex].boardEntries[boardEntryIndex] as BoardEntry )"
:selectedQuestionIndex="questionIndex ?? 0"
:isAnswerShown="true"
@questionSelected="(qIndex) => showQuestion(categoryIndex!, boardEntryIndex!, qIndex)"
/>
<BoardView
v-else
:board="( board1 as Board )"
@categorySelected="showCategory"
@boardEntrySelected="showBoardEntry" />
</div>
<div class="col-3 ps-0 h-100 overflow-auto border-start border-2 border-primary">
<CreatePanel v-model="(board1 as Board)" :categoryIndex="categoryIndex" :boardEntryIndex="boardEntryIndex" @editBoard="showBoard" @editCategory="showCategory" @editBoardEntry="showBoardEntry"/>
<CreatePanel
v-model="( board1 as Board )"
:categoryIndex="categoryIndex"
:boardEntryIndex="boardEntryIndex"
:questionIndex="questionIndex"
@editBoard="showBoard"
@editCategory="showCategory"
@editBoardEntry="showBoardEntry"
@editQuestion="showQuestion"
/>
</div>
</div>
</div>

View File

@ -52,6 +52,7 @@
"save": "Save",
"saveAndExit": "Save and Exit"
},
"back": "Back",
"error": {
"generic": "Error"
}
@ -89,6 +90,18 @@
"label": "No Entries | Entry | Entries | {count} Entries",
"add": "Add Entry",
"name": "Entry Name"
},
"question": {
"label": "No Question Layers | Question Layer | Question Layers | {count} Question Layers",
"infos": "Question Layer Infos",
"add": "Add Question Layer",
"text": "Question Text",
"type": "Question Type",
"fontsize": "Font Size",
"upload": {
"image": "Upload an image",
"audio": "Upload an audio file"
}
}
},
"theme": {

View File

@ -5,6 +5,6 @@ export class Answer{
public text: string,
public boardEntry: BoardEntry | undefined,
public image: URL | undefined = undefined,
id: number | undefined = undefined,
public id: number | undefined = undefined,
){}
}

View File

@ -7,6 +7,6 @@ export class Board{
public categories: Array<Category> = [],
public pointsAreTitle: boolean = false,
public owner: User | undefined = undefined,
private id: number | undefined = undefined,
public id: number | undefined = undefined,
){}
}

View File

@ -5,10 +5,10 @@ import type { Question } from './Question';
export class BoardEntry{
constructor(
public name: string,
public points: number,
public category: Category,
public answer: Answer,
public questions: Array<Question>,
id: number | undefined = undefined,
public points: number = 100,
public id: number | undefined = undefined,
){}
}

View File

@ -7,6 +7,6 @@ export class Category{
public description: string,
public board: Board,
public boardEntries: Array<BoardEntry> = [],
id: number | undefined = undefined,
public id: number | undefined = undefined,
){}
}

View File

@ -6,7 +6,8 @@ export class Question{
public text: string,
public questionType: QuestionType,
public boardEntry: BoardEntry,
public image: URL | undefined,
id: number | undefined = undefined,
public fontScaling: number = 3,
public image: string | undefined = undefined,
public id: number | undefined = undefined,
) {}
}

View File

@ -3,6 +3,6 @@ export class QuestionType {
public title: string,
public description: string,
public active: boolean,
id: number | undefined = undefined,
public id: number | undefined = undefined,
){}
}

View File

@ -1,6 +1,7 @@
import type NavBar from '@/components/blocks/NavBar.vue';
import type { InjectionKey, Ref } from 'vue';
import type NavBar from '@/components/blocks/NavBar.vue';
import type { QuestionType } from '@/models/board/QuestionType';
export const infoModalShowFnKey = Symbol() as InjectionKey<Function>;
export const navbarKey = Symbol() as InjectionKey<Ref<InstanceType<typeof NavBar> | undefined>>;
// export const navbarKey = Symbol() as InjectionKey<Ref<InstanceType<typeof NavBar> | null>>;
export const questionTypesKey = Symbol() as InjectionKey<Array<QuestionType>>;