@windward/games 0.0.4 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/content/DatableEditor.vue +0 -3
- package/components/content/blocks/crosswordPuzzle/Crossword.ts +231 -153
- package/components/content/blocks/crosswordPuzzle/CrosswordClues.vue +91 -0
- package/components/content/blocks/crosswordPuzzle/CrosswordElements.ts +8 -6
- package/components/content/blocks/crosswordPuzzle/CrosswordPuzzle.vue +502 -371
- package/components/content/blocks/multipleChoice/MultipleChoice.vue +187 -127
- package/components/content/blocks/multipleChoice/QuestionDialog.vue +37 -13
- package/components/content/blocks/sevenStrikes/SevenStikes.vue +368 -0
- package/components/content/blocks/sevenStrikes/keyboard.vue +71 -0
- package/components/content/blocks/wordJumble/Jumble.vue +2 -10
- package/components/settings/CrosswordPuzzleSettingsManager.vue +12 -15
- package/components/settings/MultipleChoiceSettingsManager.vue +21 -7
- package/components/settings/SevenStrikesSettingsManager.vue +288 -0
- package/i18n/en-US/components/content/blocks/crossword.ts +18 -3
- package/i18n/en-US/components/content/blocks/index.ts +2 -0
- package/i18n/en-US/components/content/blocks/multiple_choice.ts +2 -4
- package/i18n/en-US/components/content/blocks/seven_strikes.ts +6 -0
- package/i18n/en-US/components/settings/crossword.ts +2 -1
- package/i18n/en-US/components/settings/index.ts +2 -0
- package/i18n/en-US/components/settings/multiple_choice.ts +1 -1
- package/i18n/en-US/components/settings/seven_strikes.ts +8 -0
- package/i18n/en-US/shared/content_blocks.ts +1 -0
- package/i18n/en-US/shared/settings.ts +1 -0
- package/package.json +2 -1
- package/plugin.js +21 -0
- package/test/blocks/sevenStrikes/sevenStrikes.spec.js +24 -0
- package/test/settings/SevenStrikesManager.spec.js +53 -0
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
<v-col class="pa-0">
|
|
4
|
+
<h3>
|
|
5
|
+
{{
|
|
6
|
+
block.metadata.config.title
|
|
7
|
+
? block.metadata.config.title
|
|
8
|
+
: $t(
|
|
9
|
+
'plugin.games.components.content.blocks.seven_strikes.title'
|
|
10
|
+
)
|
|
11
|
+
}}
|
|
12
|
+
</h3>
|
|
13
|
+
<p>{{ block.metadata.config.instructions }}</p>
|
|
14
|
+
</v-col>
|
|
15
|
+
<v-col class="pa-0">
|
|
16
|
+
<template>
|
|
17
|
+
<v-carousel
|
|
18
|
+
v-model="carouselIndex"
|
|
19
|
+
@change="onSlideChanged($event)"
|
|
20
|
+
>
|
|
21
|
+
<v-carousel-item
|
|
22
|
+
v-for="(word, index) in block.metadata.config.words"
|
|
23
|
+
:key="index"
|
|
24
|
+
>
|
|
25
|
+
<v-row class="d-flex justify-center ma-2">
|
|
26
|
+
<p class="pa-3 mb-0 clueAndJumble">
|
|
27
|
+
{{ word.hint }}
|
|
28
|
+
</p>
|
|
29
|
+
</v-row>
|
|
30
|
+
<v-container
|
|
31
|
+
v-if="showFeedback"
|
|
32
|
+
:key="'feedback'"
|
|
33
|
+
:class="feedbackStatus"
|
|
34
|
+
class="mb-8"
|
|
35
|
+
>
|
|
36
|
+
<v-row class="d-flex" align="center">
|
|
37
|
+
<v-col cols="4"></v-col>
|
|
38
|
+
<v-col cols="4" class="d-flex justify-center">
|
|
39
|
+
<p class="">{{ feedback }}</p>
|
|
40
|
+
</v-col>
|
|
41
|
+
<v-col cols="4" class="d-flex justify-end">
|
|
42
|
+
<v-icon @click="onHideFeedback">
|
|
43
|
+
mdi-alpha-x-circle-outline</v-icon
|
|
44
|
+
>
|
|
45
|
+
</v-col>
|
|
46
|
+
</v-row>
|
|
47
|
+
</v-container>
|
|
48
|
+
<v-row class="justify-center">
|
|
49
|
+
<div
|
|
50
|
+
v-for="(
|
|
51
|
+
strike, strikeIndex
|
|
52
|
+
) in sevenStrikesCounter"
|
|
53
|
+
:key="strikeIndex"
|
|
54
|
+
>
|
|
55
|
+
<div
|
|
56
|
+
v-if="strike.strike === false"
|
|
57
|
+
:ref="'strike' + strikeIndex"
|
|
58
|
+
class="strikeArea ml-1 mr-1 d-flex justify-center align-center"
|
|
59
|
+
maxlength="1"
|
|
60
|
+
></div>
|
|
61
|
+
<div
|
|
62
|
+
class="strike"
|
|
63
|
+
v-if="strike.strike === true"
|
|
64
|
+
>
|
|
65
|
+
X
|
|
66
|
+
</div>
|
|
67
|
+
</div>
|
|
68
|
+
</v-row>
|
|
69
|
+
<v-row
|
|
70
|
+
class="justify-center mt-12"
|
|
71
|
+
v-if="word.splitWord"
|
|
72
|
+
>
|
|
73
|
+
<div
|
|
74
|
+
v-for="(letter, splitIndex) in word.splitWord"
|
|
75
|
+
:key="splitIndex"
|
|
76
|
+
>
|
|
77
|
+
<div
|
|
78
|
+
:ref="'input' + splitIndex"
|
|
79
|
+
class="textArea ml-1 mr-1"
|
|
80
|
+
maxlength="1"
|
|
81
|
+
>
|
|
82
|
+
<div v-if="letter.show === true">
|
|
83
|
+
{{ letter.letter }}
|
|
84
|
+
</div>
|
|
85
|
+
</div>
|
|
86
|
+
</div>
|
|
87
|
+
</v-row>
|
|
88
|
+
<div>
|
|
89
|
+
<keyboard
|
|
90
|
+
v-if="!showFeedback"
|
|
91
|
+
:key="index"
|
|
92
|
+
:keyboardClass="keyBoardClass + index"
|
|
93
|
+
@onChange="onChange"
|
|
94
|
+
@onKeyPress="onKeyPress"
|
|
95
|
+
:input="input"
|
|
96
|
+
/>
|
|
97
|
+
</div>
|
|
98
|
+
<v-row class="justify-center mt-12" v-if="showFeedback">
|
|
99
|
+
<v-btn
|
|
100
|
+
color="primary ml-4"
|
|
101
|
+
@click="onRevealAnswer"
|
|
102
|
+
>{{
|
|
103
|
+
$t(
|
|
104
|
+
'plugin.games.components.content.blocks.seven_strikes.reveal'
|
|
105
|
+
)
|
|
106
|
+
}}</v-btn
|
|
107
|
+
>
|
|
108
|
+
<v-btn
|
|
109
|
+
color="primary ml-4"
|
|
110
|
+
@click="onSlideChanged(index)"
|
|
111
|
+
>{{
|
|
112
|
+
$t(
|
|
113
|
+
'plugin.games.components.content.blocks.seven_strikes.again'
|
|
114
|
+
)
|
|
115
|
+
}}</v-btn
|
|
116
|
+
>
|
|
117
|
+
<v-btn
|
|
118
|
+
@click="onChangeSlide(index + 1)"
|
|
119
|
+
color="primary ml-4"
|
|
120
|
+
>{{
|
|
121
|
+
$t(
|
|
122
|
+
'plugin.games.components.content.blocks.seven_strikes.next'
|
|
123
|
+
)
|
|
124
|
+
}}</v-btn
|
|
125
|
+
>
|
|
126
|
+
</v-row>
|
|
127
|
+
</v-carousel-item>
|
|
128
|
+
</v-carousel>
|
|
129
|
+
</template>
|
|
130
|
+
</v-col>
|
|
131
|
+
</div>
|
|
132
|
+
</template>
|
|
133
|
+
|
|
134
|
+
<script>
|
|
135
|
+
import _ from 'lodash'
|
|
136
|
+
import draggable from 'vuedraggable'
|
|
137
|
+
import keyboard from './keyboard.vue'
|
|
138
|
+
import CrudTable from '../../CrudTable'
|
|
139
|
+
import BaseContentBlock from '~/components/Content/Blocks/BaseContentBlock'
|
|
140
|
+
|
|
141
|
+
export default {
|
|
142
|
+
name: 'SevenStrikesGame',
|
|
143
|
+
components: { CrudTable, draggable, keyboard },
|
|
144
|
+
extends: BaseContentBlock,
|
|
145
|
+
beforeMount() {
|
|
146
|
+
if (_.isEmpty(this.block)) {
|
|
147
|
+
this.block = {}
|
|
148
|
+
}
|
|
149
|
+
if (_.isEmpty(this.block.metadata)) {
|
|
150
|
+
this.block.metadata = {}
|
|
151
|
+
}
|
|
152
|
+
if (_.isEmpty(this.block.metadata.config)) {
|
|
153
|
+
this.block.metadata.config = {}
|
|
154
|
+
}
|
|
155
|
+
if (_.isEmpty(this.block.metadata.config.words)) {
|
|
156
|
+
this.block.metadata.config.words = []
|
|
157
|
+
}
|
|
158
|
+
},
|
|
159
|
+
data() {
|
|
160
|
+
return {
|
|
161
|
+
feedback: '',
|
|
162
|
+
feedbackStatus: '',
|
|
163
|
+
showFeedback: false,
|
|
164
|
+
input: '',
|
|
165
|
+
sevenStrikesCounter: [
|
|
166
|
+
{ strike: false },
|
|
167
|
+
{ strike: false },
|
|
168
|
+
{ strike: false },
|
|
169
|
+
{ strike: false },
|
|
170
|
+
{ strike: false },
|
|
171
|
+
{ strike: false },
|
|
172
|
+
{ strike: false },
|
|
173
|
+
],
|
|
174
|
+
keyBoardClass: 'simple-keyboard',
|
|
175
|
+
onSlide: 0,
|
|
176
|
+
onStrike: 0,
|
|
177
|
+
carouselIndex: 0,
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
mounted() {},
|
|
181
|
+
methods: {
|
|
182
|
+
onChangeSlide(newIndex) {
|
|
183
|
+
if (newIndex >= this.block.metadata.config.words.length) {
|
|
184
|
+
newIndex = 0
|
|
185
|
+
}
|
|
186
|
+
this.carouselIndex = newIndex
|
|
187
|
+
this.onSlideChanged(newIndex)
|
|
188
|
+
},
|
|
189
|
+
onChange(input) {
|
|
190
|
+
this.input = input
|
|
191
|
+
},
|
|
192
|
+
onKeyPress(letter) {
|
|
193
|
+
// can't play when editing
|
|
194
|
+
if (this.render) {
|
|
195
|
+
// to lowercase
|
|
196
|
+
letter = letter.toLowerCase()
|
|
197
|
+
// check if word value contains input letter
|
|
198
|
+
const doesContain =
|
|
199
|
+
this.block.metadata.config.words[
|
|
200
|
+
this.onSlide
|
|
201
|
+
].value.includes(letter)
|
|
202
|
+
if (doesContain) {
|
|
203
|
+
// loop over to show letters in case there are multiple of the same
|
|
204
|
+
this.block.metadata.config.words[
|
|
205
|
+
this.onSlide
|
|
206
|
+
].splitWord.forEach((character) => {
|
|
207
|
+
if (character.letter === letter) {
|
|
208
|
+
character.show = true
|
|
209
|
+
}
|
|
210
|
+
})
|
|
211
|
+
} else {
|
|
212
|
+
// checks if the user is already out of strikes
|
|
213
|
+
if (this.onStrike <= 6) {
|
|
214
|
+
this.sevenStrikesCounter[this.onStrike].strike = true
|
|
215
|
+
this.onStrike = this.onStrike + 1
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
const isComplete = this.checkIfComplete()
|
|
219
|
+
const checkStrikes = this.checkStrikes()
|
|
220
|
+
if (isComplete) {
|
|
221
|
+
this.thatIsCorrect()
|
|
222
|
+
}
|
|
223
|
+
if (checkStrikes) {
|
|
224
|
+
this.thatIsIncorrect()
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
},
|
|
228
|
+
checkIfComplete() {
|
|
229
|
+
// checks to see if the user guessed all the letters correctly
|
|
230
|
+
let finished = true
|
|
231
|
+
this.block.metadata.config.words[this.onSlide].splitWord.forEach(
|
|
232
|
+
(element) => {
|
|
233
|
+
if (element.show === false) {
|
|
234
|
+
finished = false
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
)
|
|
238
|
+
return finished
|
|
239
|
+
},
|
|
240
|
+
checkStrikes() {
|
|
241
|
+
// checks to see if user has exhausted strikes
|
|
242
|
+
let outOfStrikes = true
|
|
243
|
+
this.sevenStrikesCounter.forEach((element) => {
|
|
244
|
+
if (element.strike === false) {
|
|
245
|
+
outOfStrikes = false
|
|
246
|
+
}
|
|
247
|
+
})
|
|
248
|
+
return outOfStrikes
|
|
249
|
+
},
|
|
250
|
+
thatIsIncorrect() {
|
|
251
|
+
this.showFeedback = true
|
|
252
|
+
// updates class
|
|
253
|
+
this.feedbackStatus = 'error'
|
|
254
|
+
// gets custom or standard feedback
|
|
255
|
+
if (
|
|
256
|
+
!_.isEmpty(this.block.metadata.config.feedback_incorrect) &&
|
|
257
|
+
this.block.metadata.config.feedback_incorrect !== ''
|
|
258
|
+
) {
|
|
259
|
+
this.feedback = this.block.metadata.config.feedback_incorrect
|
|
260
|
+
} else {
|
|
261
|
+
this.feedback = this.$t(
|
|
262
|
+
'plugin.games.components.content.blocks.word_jumble.incorrect'
|
|
263
|
+
)
|
|
264
|
+
}
|
|
265
|
+
},
|
|
266
|
+
thatIsCorrect() {
|
|
267
|
+
this.showFeedback = true
|
|
268
|
+
this.feedbackStatus = 'success'
|
|
269
|
+
if (
|
|
270
|
+
!_.isEmpty(this.block.metadata.config.feedback_correct) &&
|
|
271
|
+
this.block.metadata.config.feedback_correct !== ''
|
|
272
|
+
) {
|
|
273
|
+
this.feedback = this.block.metadata.config.feedback_correct
|
|
274
|
+
} else {
|
|
275
|
+
this.feedback = this.$t(
|
|
276
|
+
'plugin.games.components.content.blocks.word_jumble.correct'
|
|
277
|
+
)
|
|
278
|
+
}
|
|
279
|
+
},
|
|
280
|
+
onHideFeedback() {
|
|
281
|
+
// fired from feedback x
|
|
282
|
+
this.showFeedback = false
|
|
283
|
+
this.onSlideChanged(this.onSlide)
|
|
284
|
+
},
|
|
285
|
+
onInputChange(input) {
|
|
286
|
+
// catches target input
|
|
287
|
+
this.input = input.target.value
|
|
288
|
+
},
|
|
289
|
+
onSlideChanged(event) {
|
|
290
|
+
// this function is called when the slide is changed
|
|
291
|
+
// manually resetting is necessary due to fact that components do not remount
|
|
292
|
+
// event hold slide index
|
|
293
|
+
this.onSlide = event
|
|
294
|
+
// hides feedback if showing
|
|
295
|
+
this.showFeedback = false
|
|
296
|
+
this.feedbackStatus = ''
|
|
297
|
+
this.onStrike = 0
|
|
298
|
+
this.feedback = this.$t(
|
|
299
|
+
'plugin.games.components.content.blocks.word_jumble.feedback'
|
|
300
|
+
)
|
|
301
|
+
// resets strikes
|
|
302
|
+
this.sevenStrikesCounter.forEach((element) => {
|
|
303
|
+
element.strike = false
|
|
304
|
+
})
|
|
305
|
+
if (
|
|
306
|
+
this.block.metadata.config.words[this.onSlide].splitWord &&
|
|
307
|
+
this.block.metadata.config.words[this.onSlide].splitWord
|
|
308
|
+
.length > 0
|
|
309
|
+
) {
|
|
310
|
+
// rehides the displayed correct letters
|
|
311
|
+
this.block.metadata.config.words[
|
|
312
|
+
this.onSlide
|
|
313
|
+
].splitWord.forEach((word) => {
|
|
314
|
+
if (word.show) {
|
|
315
|
+
word.show = false
|
|
316
|
+
}
|
|
317
|
+
})
|
|
318
|
+
}
|
|
319
|
+
},
|
|
320
|
+
onRevealAnswer() {
|
|
321
|
+
this.block.metadata.config.words[this.onSlide].splitWord.forEach(
|
|
322
|
+
(word) => {
|
|
323
|
+
word.show = true
|
|
324
|
+
}
|
|
325
|
+
)
|
|
326
|
+
},
|
|
327
|
+
},
|
|
328
|
+
}
|
|
329
|
+
</script>
|
|
330
|
+
|
|
331
|
+
<style scoped>
|
|
332
|
+
.outline {
|
|
333
|
+
border: 2px solid black;
|
|
334
|
+
border-radius: 10px;
|
|
335
|
+
}
|
|
336
|
+
.clueAndJumble {
|
|
337
|
+
font-size: 20px;
|
|
338
|
+
}
|
|
339
|
+
.spanBold {
|
|
340
|
+
font-weight: 900;
|
|
341
|
+
}
|
|
342
|
+
.error {
|
|
343
|
+
border: dashed 2px #dc3d1a;
|
|
344
|
+
background-color: #fff1f1;
|
|
345
|
+
}
|
|
346
|
+
.success {
|
|
347
|
+
border: dashed 2px #76b778;
|
|
348
|
+
background-color: #f1fff3;
|
|
349
|
+
}
|
|
350
|
+
.textArea {
|
|
351
|
+
width: 20px;
|
|
352
|
+
height: 20px;
|
|
353
|
+
border-bottom: 2px solid black;
|
|
354
|
+
display: flex;
|
|
355
|
+
justify-content: center;
|
|
356
|
+
align-items: center;
|
|
357
|
+
}
|
|
358
|
+
.strikeArea {
|
|
359
|
+
width: 40px;
|
|
360
|
+
height: 40px;
|
|
361
|
+
border: 2px solid black;
|
|
362
|
+
}
|
|
363
|
+
.strike {
|
|
364
|
+
color: #dc3d1a;
|
|
365
|
+
font-size: 40px;
|
|
366
|
+
margin: 10px;
|
|
367
|
+
}
|
|
368
|
+
</style>
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div :class="keyboardClass"></div>
|
|
3
|
+
</template>
|
|
4
|
+
|
|
5
|
+
<script>
|
|
6
|
+
import Keyboard from 'simple-keyboard'
|
|
7
|
+
import 'simple-keyboard/build/css/index.css'
|
|
8
|
+
|
|
9
|
+
export default {
|
|
10
|
+
name: 'SimpleKeyboard',
|
|
11
|
+
props: {
|
|
12
|
+
keyboardClass: {
|
|
13
|
+
default: 'simple-keyboard',
|
|
14
|
+
type: String,
|
|
15
|
+
},
|
|
16
|
+
input: {
|
|
17
|
+
type: String,
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
data: () => ({
|
|
21
|
+
keyboard: null,
|
|
22
|
+
}),
|
|
23
|
+
mounted() {
|
|
24
|
+
this.keyboard = new Keyboard(this.keyboardClass, {
|
|
25
|
+
layout: {
|
|
26
|
+
default: [
|
|
27
|
+
'q w e r t y u i o p',
|
|
28
|
+
'a s d f g h j k l',
|
|
29
|
+
'z x c v b n m',
|
|
30
|
+
],
|
|
31
|
+
},
|
|
32
|
+
onChange: this.onChange,
|
|
33
|
+
onKeyPress: this.onKeyPress,
|
|
34
|
+
})
|
|
35
|
+
},
|
|
36
|
+
methods: {
|
|
37
|
+
onChange(input) {
|
|
38
|
+
this.$emit('onChange', input)
|
|
39
|
+
},
|
|
40
|
+
onKeyPress(button) {
|
|
41
|
+
this.$emit('onKeyPress', button)
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* If you want to handle the shift and caps lock buttons
|
|
45
|
+
*/
|
|
46
|
+
if (button === '{shift}' || button === '{lock}') this.handleShift()
|
|
47
|
+
},
|
|
48
|
+
handleShift() {
|
|
49
|
+
let currentLayout = this.keyboard.options.layoutName
|
|
50
|
+
let shiftToggle = currentLayout === 'default' ? 'shift' : 'default'
|
|
51
|
+
|
|
52
|
+
this.keyboard.setOptions({
|
|
53
|
+
layoutName: shiftToggle,
|
|
54
|
+
})
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
watch: {
|
|
58
|
+
input(input) {
|
|
59
|
+
this.keyboard.setInput(input)
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
}
|
|
63
|
+
</script>
|
|
64
|
+
|
|
65
|
+
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
|
66
|
+
<style scoped>
|
|
67
|
+
.hg-theme-default {
|
|
68
|
+
padding: 55px;
|
|
69
|
+
margin-top: 25px;
|
|
70
|
+
}
|
|
71
|
+
</style>
|
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
class="textArea ml-1 mr-1"
|
|
10
10
|
maxlength="1"
|
|
11
11
|
@input="onInput($event, index)"
|
|
12
|
-
v-on:keydown="onSpaceHandler($event)"
|
|
13
12
|
></v-text-field>
|
|
14
13
|
</div>
|
|
15
14
|
</v-row>
|
|
@@ -43,8 +42,8 @@ export default {
|
|
|
43
42
|
handler(newValue) {
|
|
44
43
|
// removes students answer from input if they got it correct
|
|
45
44
|
this.splitUpWord()
|
|
46
|
-
}
|
|
47
|
-
}
|
|
45
|
+
},
|
|
46
|
+
},
|
|
48
47
|
},
|
|
49
48
|
data() {
|
|
50
49
|
return {
|
|
@@ -71,13 +70,6 @@ export default {
|
|
|
71
70
|
}
|
|
72
71
|
}
|
|
73
72
|
},
|
|
74
|
-
onSpaceHandler(event) {
|
|
75
|
-
// prevents empty space from being entered
|
|
76
|
-
if (event.keyCode === 32) {
|
|
77
|
-
event.preventDefault()
|
|
78
|
-
return false
|
|
79
|
-
}
|
|
80
|
-
},
|
|
81
73
|
onInput(event, index) {
|
|
82
74
|
// handles focusing on next element after student enters a letter
|
|
83
75
|
if (!_.isEmpty(event) && this.$refs['input' + (index + 1)]) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div>
|
|
3
|
-
<v-form ref="form" v-model="valid"
|
|
3
|
+
<v-form ref="form" v-model="valid">
|
|
4
4
|
<v-text-field
|
|
5
5
|
v-model="block.metadata.config.title"
|
|
6
6
|
:counter="50"
|
|
@@ -82,6 +82,8 @@
|
|
|
82
82
|
<v-textarea
|
|
83
83
|
v-if="item.expand"
|
|
84
84
|
outlined
|
|
85
|
+
:counter="20"
|
|
86
|
+
maxlength="20"
|
|
85
87
|
:autofocus="true"
|
|
86
88
|
:label="
|
|
87
89
|
$t(
|
|
@@ -96,15 +98,16 @@
|
|
|
96
98
|
<v-textarea
|
|
97
99
|
v-if="item.expand"
|
|
98
100
|
outlined
|
|
101
|
+
:counter="155"
|
|
102
|
+
maxlength="155"
|
|
99
103
|
:label="
|
|
100
104
|
$t(
|
|
101
|
-
'plugin.games.components.settings.crossword.
|
|
105
|
+
'plugin.games.components.settings.crossword.clue'
|
|
102
106
|
)
|
|
103
107
|
"
|
|
104
108
|
class="pt-4"
|
|
105
109
|
v-model="
|
|
106
|
-
block.metadata.config.words[index]
|
|
107
|
-
.description
|
|
110
|
+
block.metadata.config.words[index].clue
|
|
108
111
|
"
|
|
109
112
|
></v-textarea>
|
|
110
113
|
</v-card>
|
|
@@ -131,14 +134,6 @@
|
|
|
131
134
|
</v-expansion-panel>
|
|
132
135
|
</v-expansion-panels>
|
|
133
136
|
</v-form>
|
|
134
|
-
<div v-if="loading" class="text-center">
|
|
135
|
-
<v-progress-circular
|
|
136
|
-
:size="70"
|
|
137
|
-
:width="7"
|
|
138
|
-
color="primary"
|
|
139
|
-
indeterminate
|
|
140
|
-
></v-progress-circular>
|
|
141
|
-
</div>
|
|
142
137
|
</div>
|
|
143
138
|
</template>
|
|
144
139
|
|
|
@@ -168,11 +163,12 @@ export default {
|
|
|
168
163
|
if (_.isEmpty(this.block.metadata.config.words)) {
|
|
169
164
|
this.block.metadata.config.words = []
|
|
170
165
|
let counter = 0
|
|
166
|
+
// ensures that there will always be at least two crossword elements to edit
|
|
171
167
|
while (counter < 2) {
|
|
172
168
|
const default_object = {
|
|
173
169
|
id: counter,
|
|
174
170
|
word: '',
|
|
175
|
-
|
|
171
|
+
clue: '',
|
|
176
172
|
expand: false,
|
|
177
173
|
}
|
|
178
174
|
counter = counter + 1
|
|
@@ -183,19 +179,20 @@ export default {
|
|
|
183
179
|
data() {
|
|
184
180
|
return {
|
|
185
181
|
valid: true,
|
|
186
|
-
loading: false,
|
|
187
182
|
cursor: null,
|
|
188
183
|
}
|
|
189
184
|
},
|
|
190
185
|
methods: {
|
|
191
186
|
onAddElement() {
|
|
187
|
+
// closes all elements that were expanded
|
|
192
188
|
this.block.metadata.config.words.forEach((element) => {
|
|
193
189
|
element.expand = false
|
|
194
190
|
})
|
|
191
|
+
// pushes in new crossword object and expands element
|
|
195
192
|
const default_object = {
|
|
196
193
|
id: this.block.metadata.config.words.length,
|
|
197
194
|
word: '',
|
|
198
|
-
|
|
195
|
+
clue: '',
|
|
199
196
|
expand: true,
|
|
200
197
|
}
|
|
201
198
|
this.block.metadata.config.words.push(default_object)
|
|
@@ -28,13 +28,13 @@
|
|
|
28
28
|
<v-expansion-panels flat>
|
|
29
29
|
<v-expansion-panel>
|
|
30
30
|
<v-expansion-panel-header class="pa-0">
|
|
31
|
-
<
|
|
31
|
+
<h5>
|
|
32
32
|
{{
|
|
33
33
|
$t(
|
|
34
34
|
'plugin.games.components.settings.multiple_choice.questions'
|
|
35
35
|
)
|
|
36
36
|
}}
|
|
37
|
-
</
|
|
37
|
+
</h5></v-expansion-panel-header
|
|
38
38
|
>
|
|
39
39
|
<v-expansion-panel-content class="ma-0">
|
|
40
40
|
<v-container class="pa-0">
|
|
@@ -96,7 +96,7 @@
|
|
|
96
96
|
@mouseover="onHover"
|
|
97
97
|
@mouseleave="onHoverLeave"
|
|
98
98
|
@click="onOpenModal"
|
|
99
|
-
v-on:
|
|
99
|
+
v-on:keydown.enter="onOpenModal"
|
|
100
100
|
class="fullWidth"
|
|
101
101
|
:class="cursor"
|
|
102
102
|
tabindex="0"
|
|
@@ -149,6 +149,7 @@ import draggable from 'vuedraggable'
|
|
|
149
149
|
import _ from 'lodash'
|
|
150
150
|
import Dialog from '~/components/Dialog.vue'
|
|
151
151
|
import QuestionDialog from '../content/blocks/multipleChoice/QuestionDialog.vue'
|
|
152
|
+
import Crypto from '~/helpers/Crypto'
|
|
152
153
|
|
|
153
154
|
export default {
|
|
154
155
|
name: 'MultipleChoiceSettingsManager',
|
|
@@ -195,24 +196,32 @@ export default {
|
|
|
195
196
|
// when left the saveAndNew button it was causing errors
|
|
196
197
|
this.isNotEditing = false
|
|
197
198
|
} else {
|
|
199
|
+
let firstAnswerId = Crypto.id()
|
|
198
200
|
this.block.metadata.config.questions.push({
|
|
201
|
+
// crypto.id for all ids and then use filters
|
|
199
202
|
answer_options: [
|
|
200
203
|
{
|
|
201
|
-
id:
|
|
204
|
+
id: firstAnswerId,
|
|
202
205
|
value: '',
|
|
203
206
|
correctAnswer: true,
|
|
204
207
|
disabled: false,
|
|
208
|
+
chosen: false,
|
|
209
|
+
focus: false,
|
|
205
210
|
},
|
|
206
211
|
{
|
|
207
|
-
id:
|
|
212
|
+
id: Crypto.id(),
|
|
208
213
|
value: '',
|
|
209
214
|
correctAnswer: false,
|
|
210
215
|
disabled: false,
|
|
216
|
+
chosen: false,
|
|
217
|
+
focus: false,
|
|
211
218
|
},
|
|
212
219
|
],
|
|
220
|
+
correctAnswer: firstAnswerId,
|
|
213
221
|
body: '',
|
|
214
222
|
hint: '',
|
|
215
223
|
answer_description: '',
|
|
224
|
+
id: Crypto.id(),
|
|
216
225
|
})
|
|
217
226
|
this.editingIndex =
|
|
218
227
|
this.block.metadata.config.questions.length - 1
|
|
@@ -222,21 +231,26 @@ export default {
|
|
|
222
231
|
this.dialog = true
|
|
223
232
|
},
|
|
224
233
|
saveAndNewCalled() {
|
|
234
|
+
let firstAnswerId = Crypto.id()
|
|
225
235
|
this.block.metadata.config.questions.push({
|
|
226
236
|
answer_options: [
|
|
227
237
|
{
|
|
228
|
-
id:
|
|
238
|
+
id: firstAnswerId,
|
|
229
239
|
value: '',
|
|
230
240
|
correctAnswer: true,
|
|
231
241
|
disabled: false,
|
|
242
|
+
chosen: false,
|
|
232
243
|
},
|
|
233
244
|
{
|
|
234
|
-
id:
|
|
245
|
+
id: Crypto.id(),
|
|
235
246
|
value: '',
|
|
236
247
|
correctAnswer: false,
|
|
237
248
|
disabled: false,
|
|
249
|
+
chosen: false,
|
|
238
250
|
},
|
|
239
251
|
],
|
|
252
|
+
// needed to add this bc radio group needs the id of the answer in answerobjects array to set correct value
|
|
253
|
+
correctAnswer: firstAnswerId,
|
|
240
254
|
body: '',
|
|
241
255
|
hint: '',
|
|
242
256
|
answer_description: '',
|