@windward/games 0.22.0 → 0.24.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.
@@ -256,14 +256,18 @@
256
256
  <v-container class="pa-4 mb-6">
257
257
  <v-row>
258
258
  <v-col cols="12">
259
- <GenerateAIQuestionButton
260
- :course="course"
261
- :content="currentContent"
262
- :block="block"
263
- question-type="flashcard"
264
- :replace-existing-mode="replaceExisting"
265
- @click:generate="onGeneratedFlashcards"
266
- ></GenerateAIQuestionButton>
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
- GenerateAIQuestionButton,
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
- // Handler for receiving flashcards from GenerateAIQuestionButton
447
- onGeneratedFlashcards(activityData, replaceCards) {
450
+ onPluginAppendBlock(activityData) {
448
451
  this.loading = true
449
452
  try {
450
453
  // Now process the activity data
451
- if (activityData && activityData.metadata &&
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(card => ({
458
- front: { ...card.front },
459
- back: { ...card.back },
460
- side: card.side !== undefined ? card.side : true,
461
- expand: false
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
- if (replaceCards) {
465
- // Replace mode: Clear existing cards
466
- this.block.metadata.config.cards.splice(0, this.block.metadata.config.cards.length)
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
- // Add all new cards
469
- newCards.forEach(card => {
470
- this.block.metadata.config.cards.push(card)
471
- })
472
- } else {
473
- // Merge mode: Add new cards to existing ones
474
- newCards.forEach(card => {
475
- this.block.metadata.config.cards.push(card)
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
- // Update title and instructions if provided and we're in replace mode
480
- if (replaceCards) {
481
- if (activityData.metadata.config.title) {
482
- this.block.metadata.config.title = activityData.metadata.config.title
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
- if (activityData.metadata.config.instructions) {
486
- this.block.metadata.config.instructions = activityData.metadata.config.instructions
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
- replaceCards
492
- ? this.$t('windward.games.components.settings.flashcard.form.replaced_successfully')
493
- : this.$t('windward.games.components.settings.flashcard.form.added_successfully'),
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(this.$t('windward.games.components.settings.flashcard.form.invalid_response'), {
498
- duration: 5000
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(`${this.$t('windward.games.components.settings.flashcard.form.failed_to_process')}: ${errorMessage}`, {
505
- duration: 5000
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>
@@ -251,14 +251,18 @@
251
251
  <v-container class="pa-4 mb-6">
252
252
  <v-row>
253
253
  <v-col cols="12">
254
- <GenerateAIQuestionButton
255
- :course="course"
256
- :content="content"
257
- :block="block"
258
- question-type="matching_game"
259
- :replace-existing-mode="replaceExisting"
260
- @click:generate="onGeneratedMatchingGame"
261
- ></GenerateAIQuestionButton>
254
+ <PluginRef
255
+ target="contentBlockSettingTool"
256
+ :attrs="{
257
+ value: block,
258
+ course: course,
259
+ content: currentContent,
260
+ }"
261
+ :on="{
262
+ input: onPluginSetBlock,
263
+ append: onPluginAppendBlock,
264
+ }"
265
+ ></PluginRef>
262
266
  </v-col>
263
267
  </v-row>
264
268
  </v-container>
@@ -269,7 +273,7 @@
269
273
  import BaseContentSettings from '~/components/Content/Settings/BaseContentSettings.js'
270
274
  import _ from 'lodash'
271
275
  import { mapGetters } from 'vuex'
272
- import { GenerateAIQuestionButton } from '@windward/core/utils'
276
+ import PluginRef from '~/components/Core/PluginRef.vue'
273
277
  import BaseContentBlockSettings from '~/components/Content/Settings/BaseContentBlockSettings.vue'
274
278
  import SortableExpansionPanel from '~/components/Core/SortableExpansionPanel.vue'
275
279
  import Uuid from '~/helpers/Uuid'
@@ -282,7 +286,7 @@ export default {
282
286
  SortableExpansionPanel,
283
287
  ImageAssetSettings,
284
288
  BaseContentBlockSettings,
285
- GenerateAIQuestionButton
289
+ PluginRef,
286
290
  },
287
291
  beforeMount() {
288
292
  if (_.isEmpty(this.block)) {
@@ -488,129 +492,220 @@ export default {
488
492
  // holder array now has new answer positions
489
493
  this.block.metadata.config.prompts = holderArray
490
494
  },
491
- // Handler for receiving matching game data from GenerateAIQuestionButton
492
- onGeneratedMatchingGame(activityData, replaceMode) {
493
-
495
+ // Handler for receiving matching game data from Plugins
496
+ onPluginSetBlock(activityData) {
494
497
  this.loading = true
495
498
  try {
496
499
  // Process the activity data
497
- if (activityData && activityData.metadata &&
500
+ if (
501
+ activityData &&
502
+ activityData.metadata &&
498
503
  activityData.metadata.config &&
499
504
  activityData.metadata.config.answerObjects &&
500
505
  activityData.metadata.config.prompts &&
501
506
  Array.isArray(activityData.metadata.config.answerObjects) &&
502
- Array.isArray(activityData.metadata.config.prompts)) {
503
-
504
- if (replaceMode) {
505
- // Replace mode: Clear existing answers and prompts
506
- this.block.metadata.config.answerObjects.splice(0, this.block.metadata.config.answerObjects.length)
507
- this.block.metadata.config.prompts.splice(0, this.block.metadata.config.prompts.length)
507
+ Array.isArray(activityData.metadata.config.prompts)
508
+ ) {
509
+ // Replace mode: Clear existing answers and prompts
510
+ this.block.metadata.config.answerObjects.splice(
511
+ 0,
512
+ this.block.metadata.config.answerObjects.length
513
+ )
514
+ this.block.metadata.config.prompts.splice(
515
+ 0,
516
+ this.block.metadata.config.prompts.length
517
+ )
508
518
 
509
- // Add all new answer objects and prompts
510
- activityData.metadata.config.answerObjects.forEach((answerObj, index) => {
519
+ // Add all new answer objects and prompts
520
+ activityData.metadata.config.answerObjects.forEach(
521
+ (answerObj, index) => {
511
522
  this.block.metadata.config.answerObjects.push({
512
- id: index.toString(), // string id
513
- display: answerObj.display || ''
523
+ id: index.toString(), // string id
524
+ display: answerObj.display || '',
514
525
  })
515
- })
526
+ }
527
+ )
516
528
 
517
- // Add all prompts - following the exact pattern from BucketGameSettingsManager
518
- activityData.metadata.config.prompts.forEach((promptArray, index) => {
529
+ // Add all prompts - following the exact pattern from BucketGameSettingsManager
530
+ activityData.metadata.config.prompts.forEach(
531
+ (promptArray, index) => {
519
532
  this.block.metadata.config.prompts[index] = []
520
533
  if (Array.isArray(promptArray)) {
521
- promptArray.forEach(prompt => {
534
+ promptArray.forEach((prompt) => {
522
535
  // Ensure the answer object reference is correct
523
- const answerObj = this.block.metadata.config.answerObjects[index]
524
- this.block.metadata.config.prompts[index].push({
525
- id: index.toString(), // string id
526
- textOrImage: prompt.textOrImage || 'text',
536
+ const answerObj =
537
+ this.block.metadata.config
538
+ .answerObjects[index]
539
+ this.block.metadata.config.prompts[
540
+ index
541
+ ].push({
542
+ id: index.toString(), // string id
543
+ textOrImage:
544
+ prompt.textOrImage || 'text',
527
545
  prompt: prompt.prompt || '',
528
- matchExplanation: prompt.matchExplanation || this.$t('windward.games.components.settings.matching_game.form.correct_match'),
546
+ matchExplanation:
547
+ prompt.matchExplanation ||
548
+ this.$t(
549
+ 'windward.games.components.settings.matching_game.form.correct_match'
550
+ ),
529
551
  fileConfig: prompt.fileConfig || {
530
552
  hideBackground: true,
531
553
  },
532
- answer: answerObj
554
+ answer: answerObj,
533
555
  })
534
556
  })
535
557
  }
536
- })
537
- } else {
538
- // Merge mode: Add new terms and prompts to existing ones
539
- // Check if there's only one empty answer (the default one created on init)
540
- const hasOnlyEmptyAnswer = this.block.metadata.config.answerObjects.length === 1 &&
541
- this.block.metadata.config.answerObjects[0].display === '';
542
-
543
- if (hasOnlyEmptyAnswer) {
544
- // If there's only one empty answer, replace it instead of merging
545
- this.block.metadata.config.answerObjects.splice(0, 1);
546
- this.block.metadata.config.prompts.splice(0, 1);
547
558
  }
548
-
549
- const existingAnswerCount = this.block.metadata.config.answerObjects.length
559
+ )
550
560
 
551
- // Add new answer objects
552
- activityData.metadata.config.answerObjects.forEach((answerObj, index) => {
561
+ // Update title and instructions if provided and we're in replace mode
562
+
563
+ if (activityData.metadata.config.title) {
564
+ this.block.metadata.config.title =
565
+ activityData.metadata.config.title
566
+ }
567
+
568
+ if (activityData.metadata.config.instructions) {
569
+ this.block.metadata.config.instructions =
570
+ activityData.metadata.config.instructions
571
+ }
572
+
573
+ this.$toast.success(
574
+ this.$t(
575
+ 'windward.games.components.settings.matching_game.form.replaced_successfully'
576
+ ),
577
+ { duration: 3000 }
578
+ )
579
+ } else {
580
+ this.$toast.error(
581
+ this.$t(
582
+ 'windward.games.components.settings.matching_game.form.invalid_response'
583
+ ),
584
+ {
585
+ duration: 5000,
586
+ }
587
+ )
588
+ }
589
+ } catch (error) {
590
+ // Extract error message from the response
591
+ const errorMessage = error.message || 'Unknown error occurred'
592
+ this.$toast.error(
593
+ `${this.$t(
594
+ 'windward.games.components.settings.matching_game.form.failed_to_process'
595
+ )}: ${errorMessage}`,
596
+ {
597
+ duration: 5000,
598
+ }
599
+ )
600
+ } finally {
601
+ this.loading = false
602
+ }
603
+ },
604
+
605
+ onPluginAppendBlock(activityData) {
606
+ this.loading = true
607
+ try {
608
+ // Process the activity data
609
+ if (
610
+ activityData &&
611
+ activityData.metadata &&
612
+ activityData.metadata.config &&
613
+ activityData.metadata.config.answerObjects &&
614
+ activityData.metadata.config.prompts &&
615
+ Array.isArray(activityData.metadata.config.answerObjects) &&
616
+ Array.isArray(activityData.metadata.config.prompts)
617
+ ) {
618
+ // Merge mode: Add new terms and prompts to existing ones
619
+ // Check if there's only one empty answer (the default one created on init)
620
+ const hasOnlyEmptyAnswer =
621
+ this.block.metadata.config.answerObjects.length === 1 &&
622
+ this.block.metadata.config.answerObjects[0].display ===
623
+ ''
624
+
625
+ if (hasOnlyEmptyAnswer) {
626
+ // If there's only one empty answer, replace it instead of merging
627
+ this.block.metadata.config.answerObjects.splice(0, 1)
628
+ this.block.metadata.config.prompts.splice(0, 1)
629
+ }
630
+
631
+ const existingAnswerCount =
632
+ this.block.metadata.config.answerObjects.length
633
+
634
+ // Add new answer objects
635
+ activityData.metadata.config.answerObjects.forEach(
636
+ (answerObj, index) => {
553
637
  const newIndex = existingAnswerCount + index
554
638
  this.block.metadata.config.answerObjects.push({
555
- id: newIndex.toString(), // string id
556
- display: answerObj.display || ''
639
+ id: newIndex.toString(), // string id
640
+ display: answerObj.display || '',
557
641
  })
558
- })
642
+ }
643
+ )
559
644
 
560
- // Add new prompts
561
- activityData.metadata.config.prompts.forEach((promptArray, index) => {
645
+ // Add new prompts
646
+ activityData.metadata.config.prompts.forEach(
647
+ (promptArray, index) => {
562
648
  const adjustedIndex = existingAnswerCount + index
563
- this.block.metadata.config.prompts[adjustedIndex] = []
649
+ this.block.metadata.config.prompts[adjustedIndex] =
650
+ []
564
651
  if (Array.isArray(promptArray)) {
565
- promptArray.forEach(prompt => {
566
- const answerObj = this.block.metadata.config.answerObjects[adjustedIndex]
567
- this.block.metadata.config.prompts[adjustedIndex].push({
568
- id: adjustedIndex.toString(), // string id
569
- textOrImage: prompt.textOrImage || 'text',
652
+ promptArray.forEach((prompt) => {
653
+ const answerObj =
654
+ this.block.metadata.config
655
+ .answerObjects[adjustedIndex]
656
+ this.block.metadata.config.prompts[
657
+ adjustedIndex
658
+ ].push({
659
+ id: adjustedIndex.toString(), // string id
660
+ textOrImage:
661
+ prompt.textOrImage || 'text',
570
662
  prompt: prompt.prompt || '',
571
- matchExplanation: prompt.matchExplanation || this.$t('windward.games.components.settings.matching_game.form.correct_match'),
663
+ matchExplanation:
664
+ prompt.matchExplanation ||
665
+ this.$t(
666
+ 'windward.games.components.settings.matching_game.form.correct_match'
667
+ ),
572
668
  fileConfig: prompt.fileConfig || {
573
669
  hideBackground: true,
574
670
  },
575
- answer: answerObj
671
+ answer: answerObj,
576
672
  })
577
673
  })
578
674
  }
579
- })
580
- }
581
-
582
- // Update title and instructions if provided and we're in replace mode
583
- if (replaceMode) {
584
- if (activityData.metadata.config.title) {
585
- this.block.metadata.config.title = activityData.metadata.config.title
586
675
  }
587
-
588
- if (activityData.metadata.config.instructions) {
589
- this.block.metadata.config.instructions = activityData.metadata.config.instructions
590
- }
591
- }
676
+ )
592
677
 
593
678
  this.$toast.success(
594
- replaceMode
595
- ? this.$t('windward.games.components.settings.matching_game.form.replaced_successfully')
596
- : this.$t('windward.games.components.settings.matching_game.form.added_successfully'),
679
+ this.$t(
680
+ 'windward.games.components.settings.matching_game.form.added_successfully'
681
+ ),
597
682
  { duration: 3000 }
598
683
  )
599
684
  } else {
600
- this.$toast.error(this.$t('windward.games.components.settings.matching_game.form.invalid_response'), {
601
- duration: 5000
602
- })
685
+ this.$toast.error(
686
+ this.$t(
687
+ 'windward.games.components.settings.matching_game.form.invalid_response'
688
+ ),
689
+ {
690
+ duration: 5000,
691
+ }
692
+ )
603
693
  }
604
694
  } catch (error) {
605
695
  // Extract error message from the response
606
696
  const errorMessage = error.message || 'Unknown error occurred'
607
- this.$toast.error(`${this.$t('windward.games.components.settings.matching_game.form.failed_to_process')}: ${errorMessage}`, {
608
- duration: 5000
609
- })
697
+ this.$toast.error(
698
+ `${this.$t(
699
+ 'windward.games.components.settings.matching_game.form.failed_to_process'
700
+ )}: ${errorMessage}`,
701
+ {
702
+ duration: 5000,
703
+ }
704
+ )
610
705
  } finally {
611
706
  this.loading = false
612
707
  }
613
- }
708
+ },
614
709
  },
615
710
  }
616
711
  </script>