@windward/games 0.21.0 → 0.23.0
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/CHANGELOG.md +19 -0
- package/components/content/blocks/multipleChoice/MultipleChoice.vue +25 -11
- package/components/content/blocks/multipleChoice/QuestionDialog.vue +0 -9
- package/components/settings/BucketGameSettingsManager.vue +136 -96
- package/components/settings/FlashCardSlidesManager.vue +122 -51
- package/components/settings/MatchingGameManager.vue +179 -84
- package/components/settings/MultipleChoiceSettingsManager.vue +132 -0
- package/components/settings/SevenStrikesSettingsManager.vue +91 -0
- package/components/settings/SortingGameSettingsManager.vue +103 -58
- package/components/settings/WordJumbleSettingsManager.vue +157 -0
- package/i18n/en-US/components/settings/multiple_choice.ts +4 -0
- package/i18n/en-US/components/settings/word_jumble.ts +9 -0
- package/i18n/es-ES/components/settings/multiple_choice.ts +4 -0
- package/i18n/es-ES/components/settings/word_jumble.ts +9 -0
- package/i18n/sv-SE/components/settings/multiple_choice.ts +4 -0
- package/i18n/sv-SE/components/settings/word_jumble.ts +9 -0
- package/package.json +2 -2
- package/plugin.js +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## Release [0.23.0] - 2025-09-16
|
|
4
|
+
|
|
5
|
+
* Merged in feature/LE-2035/seven-strikes (pull request #259)
|
|
6
|
+
* Merged in feature/LE-1998/MC-games (pull request #258)
|
|
7
|
+
* Merged in feature/LE-1853-multiple-choice-block-optional-h (pull request #257)
|
|
8
|
+
* Merged in bugfix/MIND-6075-decouple-generateaiquestionbut (pull request #254)
|
|
9
|
+
* Merged in feature/LE-2091-multiple-choice-block-add-space- (pull request #253)
|
|
10
|
+
* Merged release/0.22.0 into feature/LE-2091-multiple-choice-block-add-space-
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
## Release [0.22.0] - 2025-08-28
|
|
14
|
+
|
|
15
|
+
* Merged in feature/LE-2036/update-core-package-v (pull request #252)
|
|
16
|
+
* Merged in feature/LE-1851-multiple-choice-block-feedback-l (pull request #251)
|
|
17
|
+
* Merged release/0.22.0 into feature/LE-1851-multiple-choice-block-feedback-l
|
|
18
|
+
* Merged in feature/LE-2036/word-jumble-gen (pull request #250)
|
|
19
|
+
* Merged in feature/LE-1851-multiple-choice-block-feedback-l (pull request #249)
|
|
20
|
+
|
|
21
|
+
|
|
3
22
|
## Release [0.21.0] - 2025-07-29
|
|
4
23
|
|
|
5
24
|
* Merged in feature/LE-1912/sorting-game-generation (pull request #246)
|
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
<div class="d-flex justify-space-between">
|
|
82
82
|
<div class="d-flex">
|
|
83
83
|
<p
|
|
84
|
-
class="mb-0"
|
|
84
|
+
class="mb-0 mr-1"
|
|
85
85
|
:aria-labelledby="answer.value"
|
|
86
86
|
>
|
|
87
87
|
{{
|
|
@@ -147,6 +147,7 @@
|
|
|
147
147
|
text
|
|
148
148
|
elevation="0"
|
|
149
149
|
class="mr-4 btn-hint"
|
|
150
|
+
:disabled="hasHint(question)"
|
|
150
151
|
@click="onHint(question)"
|
|
151
152
|
>{{
|
|
152
153
|
$t(
|
|
@@ -228,13 +229,14 @@
|
|
|
228
229
|
</div>
|
|
229
230
|
</template>
|
|
230
231
|
<template #form="{ on, attrs }">
|
|
231
|
-
<
|
|
232
|
+
<p v-bind="attrs" v-on="on">
|
|
232
233
|
<TextViewer v-if="hint" v-model="hintText"></TextViewer>
|
|
233
234
|
<TextViewer
|
|
234
235
|
v-if="answerDescriptionModal"
|
|
235
236
|
v-model="answerDescription"
|
|
237
|
+
class="dialog-text-viewer"
|
|
236
238
|
></TextViewer>
|
|
237
|
-
</
|
|
239
|
+
</p>
|
|
238
240
|
</template>
|
|
239
241
|
</DialogBox>
|
|
240
242
|
</v-carousel>
|
|
@@ -317,13 +319,23 @@ export default {
|
|
|
317
319
|
},
|
|
318
320
|
},
|
|
319
321
|
methods: {
|
|
322
|
+
hasHint(question) {
|
|
323
|
+
if (_.isEmpty(question.hint)) {
|
|
324
|
+
return true
|
|
325
|
+
}
|
|
326
|
+
return false
|
|
327
|
+
},
|
|
320
328
|
onAnswerDescription(question, answer) {
|
|
321
329
|
this.activeQuestion = question
|
|
322
330
|
this.activeAnswer = answer
|
|
323
|
-
//launches modal and displays anwer description
|
|
331
|
+
// launches modal and displays anwer description
|
|
324
332
|
this.dialog = true
|
|
325
333
|
this.answerDescriptionModal = true
|
|
326
|
-
|
|
334
|
+
if (question.metadata.config.single_feedback) {
|
|
335
|
+
this.answerDescription = question.answer_description
|
|
336
|
+
} else if (!_.isEmpty(answer.feedback)) {
|
|
337
|
+
this.answerDescription = answer.feedback
|
|
338
|
+
}
|
|
327
339
|
},
|
|
328
340
|
onChooseAnswer(answer, question) {
|
|
329
341
|
// check to see if student already answered this question
|
|
@@ -467,13 +479,12 @@ export default {
|
|
|
467
479
|
}
|
|
468
480
|
)
|
|
469
481
|
if (studentsQuestionResponse) {
|
|
470
|
-
if (
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
answer.chosen === false
|
|
482
|
+
if (
|
|
483
|
+
answer.chosen === true &&
|
|
484
|
+
(!_.isEmpty(answer.feedback) ||
|
|
485
|
+
question.metadata.config.single_feedback)
|
|
475
486
|
) {
|
|
476
|
-
return 'mdi-
|
|
487
|
+
return 'mdi-message-alert-outline'
|
|
477
488
|
}
|
|
478
489
|
}
|
|
479
490
|
},
|
|
@@ -613,4 +624,7 @@ export default {
|
|
|
613
624
|
min-width: 20% !important;
|
|
614
625
|
margin-right: 16px;
|
|
615
626
|
}
|
|
627
|
+
.dialog-text-viewer {
|
|
628
|
+
color: var(--v-primary-base);
|
|
629
|
+
}
|
|
616
630
|
</style>
|
|
@@ -18,15 +18,6 @@
|
|
|
18
18
|
@input="onCheckValidation"
|
|
19
19
|
></TextEditor>
|
|
20
20
|
</v-col>
|
|
21
|
-
<v-col xl="3" lg="3" md="4" sm="12" cols="12" v-if="false">
|
|
22
|
-
<GenerateAIQuestionButton
|
|
23
|
-
:course="course"
|
|
24
|
-
:content="content"
|
|
25
|
-
:block="block"
|
|
26
|
-
:question-type="questionType"
|
|
27
|
-
@click:generate="onQuestionGenerated"
|
|
28
|
-
></GenerateAIQuestionButton>
|
|
29
|
-
</v-col>
|
|
30
21
|
<v-col cols="12">
|
|
31
22
|
<ImageAssetSettings
|
|
32
23
|
v-model="question.question_metadata.body_asset"
|
|
@@ -196,14 +196,18 @@
|
|
|
196
196
|
<v-container class="pa-4 mb-6">
|
|
197
197
|
<v-row>
|
|
198
198
|
<v-col cols="12">
|
|
199
|
-
<
|
|
200
|
-
|
|
201
|
-
:
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
199
|
+
<PluginRef
|
|
200
|
+
target="contentBlockSettingTool"
|
|
201
|
+
:attrs="{
|
|
202
|
+
value: block,
|
|
203
|
+
course: course,
|
|
204
|
+
content: currentContent,
|
|
205
|
+
}"
|
|
206
|
+
:on="{
|
|
207
|
+
input: onPluginSetBlock,
|
|
208
|
+
append: onPluginAppendBlock,
|
|
209
|
+
}"
|
|
210
|
+
></PluginRef>
|
|
207
211
|
</v-col>
|
|
208
212
|
</v-row>
|
|
209
213
|
</v-container>
|
|
@@ -217,7 +221,6 @@ import {
|
|
|
217
221
|
MathExpressionEditor,
|
|
218
222
|
MathLiveWrapper,
|
|
219
223
|
ContentViewer,
|
|
220
|
-
GenerateAIQuestionButton
|
|
221
224
|
} from '@windward/core/utils'
|
|
222
225
|
import colors from 'vuetify/lib/util/colors'
|
|
223
226
|
import TextEditor from '~/components/Text/TextEditor'
|
|
@@ -225,6 +228,7 @@ import BaseContentBlockSettings from '~/components/Content/Settings/BaseContentB
|
|
|
225
228
|
import Crypto from '~/helpers/Crypto'
|
|
226
229
|
import BaseContentSettings from '~/components/Content/Settings/BaseContentSettings.js'
|
|
227
230
|
import SortableExpansionPanel from '~/components/Core/SortableExpansionPanel.vue'
|
|
231
|
+
import PluginRef from '~/components/Core/PluginRef.vue'
|
|
228
232
|
import Uuid from '~/helpers/Uuid'
|
|
229
233
|
|
|
230
234
|
export default {
|
|
@@ -237,9 +241,9 @@ export default {
|
|
|
237
241
|
SortableExpansionPanel,
|
|
238
242
|
BaseContentBlockSettings,
|
|
239
243
|
TextEditor,
|
|
240
|
-
|
|
244
|
+
PluginRef,
|
|
241
245
|
},
|
|
242
|
-
beforeMount() {
|
|
246
|
+
beforeMount() {
|
|
243
247
|
if (_.isEmpty(this.block)) {
|
|
244
248
|
this.block = {}
|
|
245
249
|
}
|
|
@@ -424,125 +428,161 @@ export default {
|
|
|
424
428
|
return htmlString.replace(/(<([^>]+)>)/gi, '')
|
|
425
429
|
}
|
|
426
430
|
},
|
|
427
|
-
// Handler for receiving bucket game data from
|
|
428
|
-
|
|
431
|
+
// Handler for receiving bucket game data from Plugins
|
|
432
|
+
onPluginSetBlock(activityData) {
|
|
429
433
|
this.loading = true
|
|
430
434
|
try {
|
|
431
435
|
// Process the activity data
|
|
432
|
-
if (
|
|
436
|
+
if (
|
|
437
|
+
activityData &&
|
|
438
|
+
activityData.metadata &&
|
|
433
439
|
activityData.metadata.config &&
|
|
434
440
|
activityData.metadata.config.bucket_titles &&
|
|
435
441
|
activityData.metadata.config.bucket_answers &&
|
|
436
442
|
Array.isArray(activityData.metadata.config.bucket_titles) &&
|
|
437
|
-
Array.isArray(activityData.metadata.config.bucket_answers)
|
|
438
|
-
|
|
443
|
+
Array.isArray(activityData.metadata.config.bucket_answers)
|
|
444
|
+
) {
|
|
439
445
|
// Save new buckets and answers
|
|
440
|
-
const newBuckets =
|
|
441
|
-
|
|
446
|
+
const newBuckets =
|
|
447
|
+
activityData.metadata.config.bucket_titles
|
|
448
|
+
const newAnswers =
|
|
449
|
+
activityData.metadata.config.bucket_answers
|
|
442
450
|
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
this.block.metadata.config.
|
|
451
|
+
// Replace mode: Clear existing buckets and answers
|
|
452
|
+
this.block.metadata.config.bucket_titles.splice(
|
|
453
|
+
0,
|
|
454
|
+
this.block.metadata.config.bucket_titles.length
|
|
455
|
+
)
|
|
456
|
+
this.block.metadata.config.bucket_answers.splice(
|
|
457
|
+
0,
|
|
458
|
+
this.block.metadata.config.bucket_answers.length
|
|
459
|
+
)
|
|
447
460
|
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
})
|
|
461
|
+
// Add all new buckets
|
|
462
|
+
newBuckets.forEach((bucket) => {
|
|
463
|
+
this.block.metadata.config.bucket_titles.push({
|
|
464
|
+
title: bucket.title || '',
|
|
465
|
+
color: bucket.color || colors.blueGrey.lighten5,
|
|
466
|
+
expand: false,
|
|
455
467
|
})
|
|
468
|
+
})
|
|
456
469
|
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
470
|
+
// Add all new answers
|
|
471
|
+
newAnswers.forEach((bucketAnswers, index) => {
|
|
472
|
+
this.block.metadata.config.bucket_answers[index] = []
|
|
473
|
+
if (Array.isArray(bucketAnswers)) {
|
|
474
|
+
bucketAnswers.forEach((answer) => {
|
|
475
|
+
this.block.metadata.config.bucket_answers[
|
|
476
|
+
index
|
|
477
|
+
].push({
|
|
478
|
+
bucket_index: index,
|
|
479
|
+
display: answer.display || '',
|
|
480
|
+
feedback: answer.feedback || '',
|
|
481
|
+
expand: false,
|
|
482
|
+
id: Crypto.id(),
|
|
469
483
|
})
|
|
470
|
-
}
|
|
471
|
-
})
|
|
472
|
-
} else {
|
|
473
|
-
// Merge mode: Add new buckets and answers to existing ones
|
|
474
|
-
const existingBucketCount = this.block.metadata.config.bucket_titles.length
|
|
475
|
-
|
|
476
|
-
// Add new buckets
|
|
477
|
-
newBuckets.forEach(bucket => {
|
|
478
|
-
this.block.metadata.config.bucket_titles.push({
|
|
479
|
-
title: bucket.title || '',
|
|
480
|
-
color: bucket.color || colors.blueGrey.lighten5,
|
|
481
|
-
expand: false
|
|
482
484
|
})
|
|
483
|
-
}
|
|
485
|
+
}
|
|
486
|
+
})
|
|
484
487
|
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
this.block.metadata.config.bucket_answers[adjustedIndex] = []
|
|
490
|
-
}
|
|
491
|
-
if (Array.isArray(bucketAnswers)) {
|
|
492
|
-
bucketAnswers.forEach(answer => {
|
|
493
|
-
this.block.metadata.config.bucket_answers[adjustedIndex].push({
|
|
494
|
-
bucket_index: adjustedIndex,
|
|
495
|
-
display: answer.display || '',
|
|
496
|
-
feedback: answer.feedback || '',
|
|
497
|
-
expand: false,
|
|
498
|
-
id: Crypto.id()
|
|
499
|
-
})
|
|
500
|
-
})
|
|
501
|
-
}
|
|
502
|
-
})
|
|
488
|
+
// Update title and instructions if provided and we're in replace mode
|
|
489
|
+
if (activityData.metadata.config.title) {
|
|
490
|
+
this.block.metadata.config.title =
|
|
491
|
+
activityData.metadata.config.title
|
|
503
492
|
}
|
|
504
493
|
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
}
|
|
494
|
+
if (activityData.metadata.config.instructions) {
|
|
495
|
+
this.block.metadata.config.instructions =
|
|
496
|
+
activityData.metadata.config.instructions
|
|
497
|
+
}
|
|
510
498
|
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
499
|
+
// Update feedback messages if provided
|
|
500
|
+
if (activityData.metadata.config.feedback_correct) {
|
|
501
|
+
this.block.metadata.config.feedback_correct =
|
|
502
|
+
activityData.metadata.config.feedback_correct
|
|
503
|
+
}
|
|
514
504
|
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
505
|
+
if (activityData.metadata.config.feedback_incorrect) {
|
|
506
|
+
this.block.metadata.config.feedback_incorrect =
|
|
507
|
+
activityData.metadata.config.feedback_incorrect
|
|
508
|
+
}
|
|
519
509
|
|
|
520
|
-
|
|
521
|
-
|
|
510
|
+
this.$toast.success(
|
|
511
|
+
this.$t(
|
|
512
|
+
'windward.games.components.settings.bucket_game.form.replaced_successfully'
|
|
513
|
+
),
|
|
514
|
+
{ duration: 3000 }
|
|
515
|
+
)
|
|
516
|
+
} else {
|
|
517
|
+
this.$toast.error(
|
|
518
|
+
this.$t(
|
|
519
|
+
'windward.games.components.settings.bucket_game.form.invalid_response'
|
|
520
|
+
),
|
|
521
|
+
{
|
|
522
|
+
duration: 5000,
|
|
522
523
|
}
|
|
524
|
+
)
|
|
525
|
+
}
|
|
526
|
+
} catch (error) {
|
|
527
|
+
// Extract error message from the response
|
|
528
|
+
const errorMessage = error.message || 'Unknown error occurred'
|
|
529
|
+
this.$toast.error(
|
|
530
|
+
`${this.$t(
|
|
531
|
+
'windward.games.components.settings.bucket_game.form.failed_to_process'
|
|
532
|
+
)}: ${errorMessage}`,
|
|
533
|
+
{
|
|
534
|
+
duration: 5000,
|
|
523
535
|
}
|
|
536
|
+
)
|
|
537
|
+
} finally {
|
|
538
|
+
this.loading = false
|
|
539
|
+
}
|
|
540
|
+
},
|
|
524
541
|
|
|
542
|
+
onPluginAppendBlock(activityData) {
|
|
543
|
+
this.loading = true
|
|
544
|
+
try {
|
|
545
|
+
// Process the activity data
|
|
546
|
+
if (
|
|
547
|
+
activityData &&
|
|
548
|
+
activityData.metadata &&
|
|
549
|
+
activityData.metadata.config &&
|
|
550
|
+
activityData.metadata.config.bucket_titles &&
|
|
551
|
+
activityData.metadata.config.bucket_answers &&
|
|
552
|
+
Array.isArray(activityData.metadata.config.bucket_titles) &&
|
|
553
|
+
Array.isArray(activityData.metadata.config.bucket_answers)
|
|
554
|
+
) {
|
|
525
555
|
this.$toast.success(
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
556
|
+
this.$t(
|
|
557
|
+
'windward.games.components.settings.bucket_game.form.added_successfully'
|
|
558
|
+
),
|
|
529
559
|
{ duration: 3000 }
|
|
530
560
|
)
|
|
531
561
|
} else {
|
|
532
|
-
this.$toast.error(
|
|
533
|
-
|
|
534
|
-
|
|
562
|
+
this.$toast.error(
|
|
563
|
+
this.$t(
|
|
564
|
+
'windward.games.components.settings.bucket_game.form.invalid_response'
|
|
565
|
+
),
|
|
566
|
+
{
|
|
567
|
+
duration: 5000,
|
|
568
|
+
}
|
|
569
|
+
)
|
|
535
570
|
}
|
|
536
571
|
} catch (error) {
|
|
537
572
|
// Extract error message from the response
|
|
538
573
|
const errorMessage = error.message || 'Unknown error occurred'
|
|
539
|
-
this.$toast.error(
|
|
540
|
-
|
|
541
|
-
|
|
574
|
+
this.$toast.error(
|
|
575
|
+
`${this.$t(
|
|
576
|
+
'windward.games.components.settings.bucket_game.form.failed_to_process'
|
|
577
|
+
)}: ${errorMessage}`,
|
|
578
|
+
{
|
|
579
|
+
duration: 5000,
|
|
580
|
+
}
|
|
581
|
+
)
|
|
542
582
|
} finally {
|
|
543
583
|
this.loading = false
|
|
544
584
|
}
|
|
545
|
-
}
|
|
585
|
+
},
|
|
546
586
|
},
|
|
547
587
|
}
|
|
548
588
|
</script>
|
|
@@ -256,14 +256,18 @@
|
|
|
256
256
|
<v-container class="pa-4 mb-6">
|
|
257
257
|
<v-row>
|
|
258
258
|
<v-col cols="12">
|
|
259
|
-
<
|
|
260
|
-
|
|
261
|
-
:
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
259
|
+
<PluginRef
|
|
260
|
+
target="contentBlockSettingTool"
|
|
261
|
+
:attrs="{
|
|
262
|
+
value: block,
|
|
263
|
+
course: course,
|
|
264
|
+
content: currentContent,
|
|
265
|
+
}"
|
|
266
|
+
:on="{
|
|
267
|
+
input: onPluginSetBlock,
|
|
268
|
+
append: onPluginAppendBlock,
|
|
269
|
+
}"
|
|
270
|
+
></PluginRef>
|
|
267
271
|
</v-col>
|
|
268
272
|
</v-row>
|
|
269
273
|
</v-container>
|
|
@@ -277,7 +281,6 @@ import {
|
|
|
277
281
|
MathExpressionEditor,
|
|
278
282
|
MathLiveWrapper,
|
|
279
283
|
ContentViewer,
|
|
280
|
-
GenerateAIQuestionButton
|
|
281
284
|
} from '@windward/core/utils'
|
|
282
285
|
import BaseContentSettings from '~/components/Content/Settings/BaseContentSettings.js'
|
|
283
286
|
import ContentBlockAsset from '~/components/Content/ContentBlockAsset.vue'
|
|
@@ -286,6 +289,7 @@ import SortableExpansionPanel from '~/components/Core/SortableExpansionPanel.vue
|
|
|
286
289
|
import Uuid from '~/helpers/Uuid'
|
|
287
290
|
import BaseContentBlockSettings from '~/components/Content/Settings/BaseContentBlockSettings.vue'
|
|
288
291
|
import ImageAssetSettings from '~/components/Content/Settings/ImageAssetSettings.vue'
|
|
292
|
+
import PluginRef from '~/components/Core/PluginRef.vue'
|
|
289
293
|
|
|
290
294
|
export default {
|
|
291
295
|
name: 'FlashCardSlidesManager',
|
|
@@ -299,7 +303,7 @@ export default {
|
|
|
299
303
|
SortableExpansionPanel,
|
|
300
304
|
BaseContentBlockSettings,
|
|
301
305
|
ImageAssetSettings,
|
|
302
|
-
|
|
306
|
+
PluginRef,
|
|
303
307
|
},
|
|
304
308
|
data() {
|
|
305
309
|
return {
|
|
@@ -443,71 +447,138 @@ export default {
|
|
|
443
447
|
}
|
|
444
448
|
return htmlString.replace(/(<([^>]+)>)/gi, '')
|
|
445
449
|
},
|
|
446
|
-
|
|
447
|
-
onGeneratedFlashcards(activityData, replaceCards) {
|
|
450
|
+
onPluginAppendBlock(activityData) {
|
|
448
451
|
this.loading = true
|
|
449
452
|
try {
|
|
450
453
|
// Now process the activity data
|
|
451
|
-
if (
|
|
454
|
+
if (
|
|
455
|
+
activityData &&
|
|
456
|
+
activityData.metadata &&
|
|
452
457
|
activityData.metadata.config &&
|
|
453
458
|
activityData.metadata.config.cards &&
|
|
454
|
-
Array.isArray(activityData.metadata.config.cards)
|
|
455
|
-
|
|
459
|
+
Array.isArray(activityData.metadata.config.cards)
|
|
460
|
+
) {
|
|
456
461
|
// Save new cards
|
|
457
|
-
const newCards = activityData.metadata.config.cards.map(
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
462
|
+
const newCards = activityData.metadata.config.cards.map(
|
|
463
|
+
(card) => ({
|
|
464
|
+
front: { ...card.front },
|
|
465
|
+
back: { ...card.back },
|
|
466
|
+
side: card.side !== undefined ? card.side : true,
|
|
467
|
+
expand: false,
|
|
468
|
+
})
|
|
469
|
+
)
|
|
463
470
|
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
this.block.metadata.config.cards.
|
|
471
|
+
// Merge mode: Add new cards to existing ones
|
|
472
|
+
newCards.forEach((card) => {
|
|
473
|
+
this.block.metadata.config.cards.push(card)
|
|
474
|
+
})
|
|
467
475
|
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
476
|
+
this.$toast.success(
|
|
477
|
+
this.$t(
|
|
478
|
+
'windward.games.components.settings.flashcard.form.added_successfully'
|
|
479
|
+
),
|
|
480
|
+
{ duration: 3000 }
|
|
481
|
+
)
|
|
482
|
+
} else {
|
|
483
|
+
this.$toast.error(
|
|
484
|
+
this.$t(
|
|
485
|
+
'windward.games.components.settings.flashcard.form.invalid_response'
|
|
486
|
+
),
|
|
487
|
+
{
|
|
488
|
+
duration: 5000,
|
|
489
|
+
}
|
|
490
|
+
)
|
|
491
|
+
}
|
|
492
|
+
} catch (error) {
|
|
493
|
+
// Extract error message from the response
|
|
494
|
+
const errorMessage = error.message || 'Unknown error occurred'
|
|
495
|
+
this.$toast.error(
|
|
496
|
+
`${this.$t(
|
|
497
|
+
'windward.games.components.settings.flashcard.form.failed_to_process'
|
|
498
|
+
)}: ${errorMessage}`,
|
|
499
|
+
{
|
|
500
|
+
duration: 5000,
|
|
477
501
|
}
|
|
502
|
+
)
|
|
503
|
+
} finally {
|
|
504
|
+
this.loading = false
|
|
505
|
+
}
|
|
506
|
+
},
|
|
507
|
+
// Handler for receiving flashcards from Plugins
|
|
508
|
+
onPluginSetBlock(activityData) {
|
|
509
|
+
this.loading = true
|
|
510
|
+
try {
|
|
511
|
+
// Now process the activity data
|
|
512
|
+
if (
|
|
513
|
+
activityData &&
|
|
514
|
+
activityData.metadata &&
|
|
515
|
+
activityData.metadata.config &&
|
|
516
|
+
activityData.metadata.config.cards &&
|
|
517
|
+
Array.isArray(activityData.metadata.config.cards)
|
|
518
|
+
) {
|
|
519
|
+
// Save new cards
|
|
520
|
+
const newCards = activityData.metadata.config.cards.map(
|
|
521
|
+
(card) => ({
|
|
522
|
+
front: { ...card.front },
|
|
523
|
+
back: { ...card.back },
|
|
524
|
+
side: card.side !== undefined ? card.side : true,
|
|
525
|
+
expand: false,
|
|
526
|
+
})
|
|
527
|
+
)
|
|
478
528
|
|
|
479
|
-
//
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
529
|
+
// Replace mode: Clear existing cards
|
|
530
|
+
this.block.metadata.config.cards.splice(
|
|
531
|
+
0,
|
|
532
|
+
this.block.metadata.config.cards.length
|
|
533
|
+
)
|
|
484
534
|
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
535
|
+
// Add all new cards
|
|
536
|
+
newCards.forEach((card) => {
|
|
537
|
+
this.block.metadata.config.cards.push(card)
|
|
538
|
+
})
|
|
539
|
+
|
|
540
|
+
// Update title and instructions
|
|
541
|
+
if (activityData.metadata.config.title) {
|
|
542
|
+
this.block.metadata.config.title =
|
|
543
|
+
activityData.metadata.config.title
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
if (activityData.metadata.config.instructions) {
|
|
547
|
+
this.block.metadata.config.instructions =
|
|
548
|
+
activityData.metadata.config.instructions
|
|
488
549
|
}
|
|
489
550
|
|
|
490
551
|
this.$toast.success(
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
552
|
+
this.$t(
|
|
553
|
+
'windward.games.components.settings.flashcard.form.replaced_successfully'
|
|
554
|
+
),
|
|
494
555
|
{ duration: 3000 }
|
|
495
556
|
)
|
|
496
557
|
} else {
|
|
497
|
-
this.$toast.error(
|
|
498
|
-
|
|
499
|
-
|
|
558
|
+
this.$toast.error(
|
|
559
|
+
this.$t(
|
|
560
|
+
'windward.games.components.settings.flashcard.form.invalid_response'
|
|
561
|
+
),
|
|
562
|
+
{
|
|
563
|
+
duration: 5000,
|
|
564
|
+
}
|
|
565
|
+
)
|
|
500
566
|
}
|
|
501
567
|
} catch (error) {
|
|
502
568
|
// Extract error message from the response
|
|
503
569
|
const errorMessage = error.message || 'Unknown error occurred'
|
|
504
|
-
this.$toast.error(
|
|
505
|
-
|
|
506
|
-
|
|
570
|
+
this.$toast.error(
|
|
571
|
+
`${this.$t(
|
|
572
|
+
'windward.games.components.settings.flashcard.form.failed_to_process'
|
|
573
|
+
)}: ${errorMessage}`,
|
|
574
|
+
{
|
|
575
|
+
duration: 5000,
|
|
576
|
+
}
|
|
577
|
+
)
|
|
507
578
|
} finally {
|
|
508
579
|
this.loading = false
|
|
509
580
|
}
|
|
510
|
-
}
|
|
581
|
+
},
|
|
511
582
|
},
|
|
512
583
|
}
|
|
513
584
|
</script>
|