@windward/games 0.0.1

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.
Files changed (68) hide show
  1. package/.editorconfig +13 -0
  2. package/.eslintrc.js +11 -0
  3. package/.prettierrc +4 -0
  4. package/README.md +43 -0
  5. package/babel.config.js +1 -0
  6. package/components/content/CrudTable.vue +295 -0
  7. package/components/content/DataTableRowHandler.vue +113 -0
  8. package/components/content/DatableEditor.vue +223 -0
  9. package/components/content/blocks/BaseContentBlock.vue +8 -0
  10. package/components/content/blocks/dragDrop/BucketGame.vue +520 -0
  11. package/components/content/blocks/dragDrop/SortingGame.vue +303 -0
  12. package/components/content/blocks/flashcards/CardFace.vue +112 -0
  13. package/components/content/blocks/flashcards/Flashcard.vue +150 -0
  14. package/components/content/blocks/flashcards/FlashcardSlides.vue +121 -0
  15. package/components/content/blocks/matchingGame/MatchingGame.vue +545 -0
  16. package/components/content/blocks/quizshowGame/AnswerPanel.vue +338 -0
  17. package/components/content/blocks/quizshowGame/Gridview.vue +260 -0
  18. package/components/content/blocks/quizshowGame/QuizShow.vue +516 -0
  19. package/components/content/blocks/quizshowGame/feedbackIcons.vue +41 -0
  20. package/components/content/blocks/slideshow/SlideShow.vue +175 -0
  21. package/components/settings/BucketGameSettingsManager.vue +683 -0
  22. package/components/settings/FlashCardSlidesManager.vue +489 -0
  23. package/components/settings/MatchingGameManager.vue +775 -0
  24. package/components/settings/QuizShowSettingsManager.vue +408 -0
  25. package/components/settings/SlideShowManager.vue +248 -0
  26. package/components/settings/SortingGameSettingsManager.vue +286 -0
  27. package/i18n/en-US/components/content/blocks/bucket_game.ts +39 -0
  28. package/i18n/en-US/components/content/blocks/flashcard.ts +5 -0
  29. package/i18n/en-US/components/content/blocks/index.ts +15 -0
  30. package/i18n/en-US/components/content/blocks/matching_game.ts +26 -0
  31. package/i18n/en-US/components/content/blocks/quizshow_game.ts +35 -0
  32. package/i18n/en-US/components/content/blocks/slideshow.ts +13 -0
  33. package/i18n/en-US/components/content/blocks/sorting_game.ts +5 -0
  34. package/i18n/en-US/components/content/crud_table.ts +6 -0
  35. package/i18n/en-US/components/content/index.ts +7 -0
  36. package/i18n/en-US/components/index.ts +9 -0
  37. package/i18n/en-US/components/navigation/index.ts +5 -0
  38. package/i18n/en-US/components/settings/bucket_game.ts +35 -0
  39. package/i18n/en-US/components/settings/flashcard.ts +26 -0
  40. package/i18n/en-US/components/settings/index.ts +13 -0
  41. package/i18n/en-US/components/settings/matching_game.ts +15 -0
  42. package/i18n/en-US/components/settings/quizshow_game.ts +14 -0
  43. package/i18n/en-US/components/settings/slideshow.ts +11 -0
  44. package/i18n/en-US/index.ts +15 -0
  45. package/i18n/en-US/modules/index.ts +5 -0
  46. package/i18n/en-US/pages/index.ts +5 -0
  47. package/i18n/en-US/shared/content_blocks.ts +14 -0
  48. package/i18n/en-US/shared/index.ts +7 -0
  49. package/i18n/en-US/shared/settings.ts +10 -0
  50. package/i18n/en-US.ts +5 -0
  51. package/jest.config.js +18 -0
  52. package/package.json +51 -0
  53. package/plugin.js +150 -0
  54. package/test/blocks/dragDrop/BucketGame.spec.js +26 -0
  55. package/test/blocks/dragDrop/SortingGame.spec.js +47 -0
  56. package/test/blocks/flashcards/CardFace.spec.js +21 -0
  57. package/test/blocks/flashcards/FlashCardSlides.spec.js +24 -0
  58. package/test/blocks/flashcards/Flashcard.spec.js +24 -0
  59. package/test/blocks/matchingGame/MatchingGame.spec.js +26 -0
  60. package/test/blocks/quizShow/quizShow.spec.js +31 -0
  61. package/test/blocks/slideshow/slideshow.spec.js +24 -0
  62. package/test/mocks.js +2 -0
  63. package/test/settings/BucketGameManager.spec.js +125 -0
  64. package/test/settings/FlashCardSlidesManager.spec.js +24 -0
  65. package/test/settings/MatchingGameManager.spec.js +30 -0
  66. package/test/settings/SlideShowManager.spec.js +30 -0
  67. package/test/settings/SortingGameManager.spec.js +71 -0
  68. package/tsconfig.json +20 -0
@@ -0,0 +1,516 @@
1
+ <template>
2
+ <div>
3
+ <v-switch
4
+ v-if="!render"
5
+ v-model="tableMode"
6
+ class="text-capitalize"
7
+ :label="
8
+ $t(
9
+ 'plugin.games.components.content.blocks.quizshow_game.spreadsheet_mode'
10
+ )
11
+ "
12
+ ></v-switch>
13
+ <div v-if="!tableMode">
14
+ <div>
15
+ <h1
16
+ :aria-label="
17
+ $t(
18
+ 'plugin.games.components.content.blocks.quizshow_game.title'
19
+ )
20
+ "
21
+ tabindex="0"
22
+ >
23
+ {{ block.metadata.config.title }}
24
+ </h1>
25
+
26
+ <p tabindex="0">
27
+ <TextViewer v-model="block.metadata.config.instructions" />
28
+ </p>
29
+ <p tabindex="0">
30
+ {{
31
+ $t(
32
+ 'plugin.games.components.content.blocks.quizshow_game.basic_instructions'
33
+ )
34
+ }}
35
+ </p>
36
+
37
+ <v-container
38
+ class="d-flex flex-row flex-wrap flex-fill"
39
+ v-if="show"
40
+ >
41
+ <v-card
42
+ v-for="(category, cat_index) in block.metadata.config
43
+ .categories"
44
+ :key="cat_index"
45
+ class="flex-fill"
46
+ outlined
47
+ tile
48
+ :max-width="
49
+ block.metadata.config.responsive
50
+ ? '100%'
51
+ : 100 /
52
+ block.metadata.config.categories.length +
53
+ '%'
54
+ "
55
+ >
56
+ <v-row
57
+ align="center"
58
+ justify="center"
59
+ class="ma-1 text-capitalize font-weight-bold"
60
+ >{{ category }}
61
+ </v-row>
62
+ <v-col
63
+ v-for="(point, point_index) in block.metadata.config
64
+ .points"
65
+ :key="'btn' + point_index"
66
+ >
67
+ <v-row align="center" justify="center">
68
+ <v-btn
69
+ outlined
70
+ :color="
71
+ getButtonColor(cat_index, point_index)
72
+ "
73
+ class="flex-fill ma-2 pa-5"
74
+ @click="quizshow(cat_index, point_index)"
75
+ >
76
+ <span class="text--primary">{{
77
+ point
78
+ }}</span>
79
+ <feedback-icons
80
+ v-if="!render"
81
+ :success="
82
+ editorFeedback(
83
+ cat_index,
84
+ point_index
85
+ )
86
+ "
87
+ :icons="editorFeedbackIcons"
88
+ />
89
+ <feedback-icons
90
+ v-if="
91
+ render &&
92
+ options.answers[cat_index][
93
+ point_index
94
+ ] !== null
95
+ "
96
+ :success="
97
+ options.answers[cat_index][
98
+ point_index
99
+ ]
100
+ "
101
+ />
102
+ </v-btn>
103
+ </v-row>
104
+ </v-col>
105
+ </v-card>
106
+ </v-container>
107
+ </div>
108
+ <v-fade-transition>
109
+ <answer-panel
110
+ :edit-mode="!render"
111
+ v-if="!show"
112
+ :points="
113
+ Number(block.metadata.config.points[selectedPointIndex])
114
+ "
115
+ :state="answerStates[selectedCatIndex][selectedPointIndex]"
116
+ v-model="
117
+ options.questions[selectedCatIndex][selectedPointIndex]
118
+ "
119
+ @click-answer="getUserInput"
120
+ />
121
+ </v-fade-transition>
122
+ <v-row
123
+ align="center"
124
+ justify="center"
125
+ class="pt-4 ma-4"
126
+ v-if="!show"
127
+ >
128
+ <v-btn
129
+ class="text-capitalize"
130
+ color="secondary"
131
+ @click="show = !show"
132
+ >
133
+ <v-icon>mdi-chevron-left</v-icon>
134
+ {{
135
+ $t(
136
+ 'plugin.games.components.content.blocks.quizshow_game.return_to_questions'
137
+ )
138
+ }}
139
+ </v-btn>
140
+ </v-row>
141
+ <v-row
142
+ align="center"
143
+ justify="center"
144
+ class="pt-4 ma-4"
145
+ v-if="show"
146
+ >
147
+ <v-btn
148
+ outlined
149
+ class="text-capitalize"
150
+ color="secondary"
151
+ @click="resetGame"
152
+ >
153
+ {{ $t('shared.forms.reset') }}
154
+ </v-btn>
155
+ </v-row>
156
+ <v-row
157
+ align="center"
158
+ justify="center"
159
+ class="pt-4 ma-4 font-weight-bold text-capitalize"
160
+ v-if="show"
161
+ >
162
+ {{
163
+ $t(
164
+ 'plugin.games.components.content.blocks.quizshow_game.total_score'
165
+ ) +
166
+ ' ' +
167
+ totalScore()
168
+ }}
169
+ </v-row>
170
+ </div>
171
+ <gridview v-if="tableMode" v-model="gridViewModel" />
172
+ </div>
173
+ </template>
174
+
175
+ <script>
176
+ import _ from 'lodash'
177
+ import BaseContentBlock from '~/components/Content/Blocks/BaseContentBlock'
178
+ import AnswerPanel from './AnswerPanel'
179
+ import FeedbackIcons from './feedbackIcons'
180
+ import Gridview from './Gridview'
181
+ import TextViewer from '~/components/Text/TextViewer.vue'
182
+
183
+ export default {
184
+ name: 'quizshow',
185
+ components: { Gridview, FeedbackIcons, AnswerPanel, TextViewer },
186
+ extends: BaseContentBlock,
187
+ data() {
188
+ return {
189
+ saveState: false,
190
+ show: true,
191
+ tableMode: false,
192
+ options: {
193
+ categories: [],
194
+ questions: [],
195
+ answers: [],
196
+ },
197
+ answerStates: [],
198
+ selectedCatIndex: 0,
199
+ selectedPointIndex: 0,
200
+ hello: '',
201
+ }
202
+ },
203
+ beforeMount() {
204
+ if (!_.isEmpty(this.body)) {
205
+ this.options = this.body
206
+ }
207
+
208
+ if (this.options.questions.length === 0) {
209
+ for (let index = 0; index < 10; index++) {
210
+ this.options.questions[index] = []
211
+ for (let point_index = 0; point_index < 10; point_index++) {
212
+ this.options.questions[index][point_index] = {}
213
+ }
214
+ }
215
+ }
216
+ if (this.options.answers.length === 0) {
217
+ this.initAnswers()
218
+ }
219
+ if (this.answerStates.length === 0) {
220
+ this.initAnswersStates()
221
+ }
222
+ },
223
+ mounted() {},
224
+ updated() {},
225
+ computed: {
226
+ editorFeedbackIcons() {
227
+ if (this.render) {
228
+ return {
229
+ success: 'mdi-check-circle-outline',
230
+ error: 'mdi-close-circle-outline',
231
+ }
232
+ } else {
233
+ return {
234
+ success: 'mdi-check-circle-outline',
235
+ error: 'mdi-alert-circle-outline',
236
+ }
237
+ }
238
+ },
239
+ rows() {
240
+ return this.block.metadata.config.maxRows
241
+ ? Number(this.block.metadata.config.maxRows)
242
+ : 0
243
+ },
244
+ gridViewModel: {
245
+ get() {
246
+ let model = []
247
+ if (
248
+ _.isArray(this.block.metadata.config.categories) &&
249
+ this.block.metadata.config.categories.length > 0
250
+ ) {
251
+ for (
252
+ let cat_index = 0;
253
+ cat_index <
254
+ this.block.metadata.config.categories.length;
255
+ cat_index++
256
+ ) {
257
+ for (
258
+ let point_index = 0;
259
+ point_index <
260
+ this.block.metadata.config.points.length;
261
+ point_index++
262
+ ) {
263
+ model.push({
264
+ cat_index: cat_index,
265
+ category:
266
+ this.block.metadata.config.categories[
267
+ cat_index
268
+ ],
269
+ point_index: point_index,
270
+ points: this.block.metadata.config.points[
271
+ point_index
272
+ ],
273
+ answer: _.isNumber(
274
+ this.options.questions[cat_index][
275
+ point_index
276
+ ].answer
277
+ )
278
+ ? Number(
279
+ this.options.questions[cat_index][
280
+ point_index
281
+ ].answer
282
+ ) + 1
283
+ : '',
284
+ question:
285
+ this.options.questions[cat_index][
286
+ point_index
287
+ ].text,
288
+ choice_1:
289
+ _.isArray(
290
+ this.options.questions[cat_index][
291
+ point_index
292
+ ].choices
293
+ ) &&
294
+ this.options.questions[cat_index][
295
+ point_index
296
+ ].choices.length > 0
297
+ ? this.options.questions[cat_index][
298
+ point_index
299
+ ].choices[0].text
300
+ : '',
301
+ choice_2:
302
+ _.isArray(
303
+ this.options.questions[cat_index][
304
+ point_index
305
+ ].choices
306
+ ) &&
307
+ this.options.questions[cat_index][
308
+ point_index
309
+ ].choices.length > 1
310
+ ? this.options.questions[cat_index][
311
+ point_index
312
+ ].choices[1].text
313
+ : '',
314
+ choice_3:
315
+ _.isArray(
316
+ this.options.questions[cat_index][
317
+ point_index
318
+ ].choices
319
+ ) &&
320
+ this.options.questions[cat_index][
321
+ point_index
322
+ ].choices.length > 2
323
+ ? this.options.questions[cat_index][
324
+ point_index
325
+ ].choices[2].text
326
+ : '',
327
+ choice_4:
328
+ _.isArray(
329
+ this.options.questions[cat_index][
330
+ point_index
331
+ ].choices
332
+ ) &&
333
+ this.options.questions[cat_index][
334
+ point_index
335
+ ].choices.length > 3
336
+ ? this.options.questions[cat_index][
337
+ point_index
338
+ ].choices[3].text
339
+ : '',
340
+ })
341
+ }
342
+ }
343
+ }
344
+
345
+ return model
346
+ },
347
+ set(newValue) {
348
+ const context = this
349
+ newValue.forEach(function (item) {
350
+ if (
351
+ context.options.questions[item.cat_index][
352
+ item.point_index
353
+ ].text === 'undefined'
354
+ ) {
355
+ context.options.questions[item.cat_index][
356
+ item.point_index
357
+ ] = {
358
+ text: '',
359
+ answer: '',
360
+ choices: [],
361
+ }
362
+ }
363
+ context.options.questions[item.cat_index][
364
+ item.point_index
365
+ ] = {
366
+ text: item.question,
367
+ answer:
368
+ Number(item.answer) > 0
369
+ ? Number(item.answer) - 1
370
+ : null,
371
+ choices: context.makeChoiceArray(item),
372
+ }
373
+ })
374
+ },
375
+ },
376
+ },
377
+ methods: {
378
+ resetGame() {
379
+ this.initAnswers()
380
+ this.initAnswersStates()
381
+ this.$forceUpdate()
382
+ },
383
+ initAnswers() {
384
+ for (let index = 0; index < 10; index++) {
385
+ this.options.answers[index] = []
386
+ for (let point_index = 0; point_index < 10; point_index++) {
387
+ this.options.answers[index][point_index] = null
388
+ }
389
+ }
390
+ },
391
+ initAnswersStates() {
392
+ for (let index = 0; index < 10; index++) {
393
+ this.answerStates[index] = []
394
+ for (let point_index = 0; point_index < 10; point_index++) {
395
+ this.answerStates[index][point_index] = null
396
+ }
397
+ }
398
+ },
399
+ makeChoiceArray(item) {
400
+ let item_choices = [
401
+ item.choice_1,
402
+ item.choice_2,
403
+ item.choice_3,
404
+ item.choice_4,
405
+ ]
406
+ const answer = item.answer
407
+ let choices = item_choices
408
+ .map(function (lineItem, index) {
409
+ if (lineItem.length > 0) {
410
+ return {
411
+ text: lineItem,
412
+ is_answer:
413
+ Number(answer) > 0
414
+ ? Number(answer) - 1 === index
415
+ : false,
416
+ }
417
+ }
418
+ })
419
+ .filter((item) => item !== undefined)
420
+ return choices
421
+ },
422
+ totalScore() {
423
+ let total = 0
424
+ if (this.block.metadata.config.categories) {
425
+ for (
426
+ let index = 0;
427
+ index < this.block.metadata.config.categories.length;
428
+ index++
429
+ ) {
430
+ for (
431
+ let point_index = 0;
432
+ point_index < this.block.metadata.config.points.length;
433
+ point_index++
434
+ ) {
435
+ if (this.options.answers[index][point_index] === true) {
436
+ total += Number(
437
+ this.block.metadata.config.points[point_index]
438
+ )
439
+ }
440
+ }
441
+ }
442
+ }
443
+
444
+ return total
445
+ },
446
+ getUserInput(event) {
447
+ this.options.answers[this.selectedCatIndex][
448
+ this.selectedPointIndex
449
+ ] = event.result
450
+ this.answerStates[this.selectedCatIndex][this.selectedPointIndex] =
451
+ { userInput: event.userInput, result: event.result }
452
+ },
453
+ editorFeedback(cat_index, point_index) {
454
+ if (
455
+ this.options.questions[cat_index][point_index] &&
456
+ _.isNumber(
457
+ this.options.questions[cat_index][point_index].answer
458
+ ) &&
459
+ this.options.questions[cat_index][point_index].text.length > 0
460
+ ) {
461
+ return true
462
+ } else {
463
+ return false
464
+ }
465
+ },
466
+ userFeedback(cat_index, point_index) {
467
+ if (this.options.answers[cat_index][point_index]) {
468
+ return true
469
+ } else {
470
+ return false
471
+ }
472
+ },
473
+ async onActionPanelEdit() {
474
+ this.render = !this.render
475
+
476
+ if (this.tableMode) {
477
+ this.tableMode = false
478
+ }
479
+ },
480
+ async onBeforeSave() {
481
+ this.emitBody({
482
+ questions: this.options.questions,
483
+ categories: this.options.categories,
484
+ answers: [],
485
+ })
486
+ },
487
+ quizshow(catIndex, pointIndex) {
488
+ this.selectedCatIndex = catIndex
489
+ this.selectedPointIndex = pointIndex
490
+ this.show = !this.show
491
+ },
492
+ getButtonColor(cat_index, point_index) {
493
+ if (!this.render) {
494
+ if (this.editorFeedback(cat_index, point_index)) {
495
+ return 'success'
496
+ }
497
+ return 'error'
498
+ }
499
+ if (
500
+ this.render &&
501
+ this.options.answers[cat_index][point_index] !== null
502
+ ) {
503
+ if (this.userFeedback(cat_index, point_index)) {
504
+ return 'success'
505
+ } else {
506
+ return 'error'
507
+ }
508
+ } else {
509
+ return 'secondary'
510
+ }
511
+ },
512
+ },
513
+ }
514
+ </script>
515
+
516
+ <style scoped></style>
@@ -0,0 +1,41 @@
1
+ <template>
2
+ <div>
3
+ <span class="sr-only">
4
+ {{
5
+ $t(
6
+ 'plugin.games.components.content.blocks.quizshow_game.success'
7
+ )
8
+ }}</span
9
+ >
10
+ <v-icon color="success" v-if="success">
11
+ {{ icons.success }}
12
+ </v-icon>
13
+ <span class="sr-only">
14
+ {{
15
+ $t('plugin.games.components.content.blocks.quizshow_game.error')
16
+ }}</span
17
+ >
18
+ <v-icon color="error" v-if="!success">
19
+ {{ icons.error }}
20
+ </v-icon>
21
+ </div>
22
+ </template>
23
+
24
+ <script>
25
+ export default {
26
+ name: 'feedbackIcons',
27
+ props: {
28
+ success: { type: Boolean, required: true },
29
+ icons: {
30
+ type: Object,
31
+ required: false,
32
+ default: {
33
+ success: 'mdi-check-circle-outline',
34
+ error: 'mdi-close-circle-outline',
35
+ },
36
+ },
37
+ },
38
+ }
39
+ </script>
40
+
41
+ <style scoped></style>