@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 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
- <div v-bind="attrs" v-on="on">
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
- </div>
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
- this.answerDescription = question.answer_description
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 (answer.correctAnswer === true && answer.chosen === true) {
471
- return 'mdi-information'
472
- } else if (
473
- answer.correctAnswer === true &&
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-information-outline'
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
- <GenerateAIQuestionButton
200
- :course="course"
201
- :content="currentContent"
202
- :block="block"
203
- question-type="bucket_game"
204
- :replace-existing-mode="replaceExisting"
205
- @click:generate="onGeneratedBucketGame"
206
- ></GenerateAIQuestionButton>
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
- GenerateAIQuestionButton,
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 GenerateAIQuestionButton
428
- onGeneratedBucketGame(activityData, replaceMode) {
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 (activityData && activityData.metadata &&
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 = activityData.metadata.config.bucket_titles
441
- const newAnswers = activityData.metadata.config.bucket_answers
446
+ const newBuckets =
447
+ activityData.metadata.config.bucket_titles
448
+ const newAnswers =
449
+ activityData.metadata.config.bucket_answers
442
450
 
443
- if (replaceMode) {
444
- // Replace mode: Clear existing buckets and answers
445
- this.block.metadata.config.bucket_titles.splice(0, this.block.metadata.config.bucket_titles.length)
446
- this.block.metadata.config.bucket_answers.splice(0, this.block.metadata.config.bucket_answers.length)
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
- // Add all new buckets
449
- newBuckets.forEach(bucket => {
450
- this.block.metadata.config.bucket_titles.push({
451
- title: bucket.title || '',
452
- color: bucket.color || colors.blueGrey.lighten5,
453
- expand: false
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
- // Add all new answers
458
- newAnswers.forEach((bucketAnswers, index) => {
459
- this.block.metadata.config.bucket_answers[index] = []
460
- if (Array.isArray(bucketAnswers)) {
461
- bucketAnswers.forEach(answer => {
462
- this.block.metadata.config.bucket_answers[index].push({
463
- bucket_index: index,
464
- display: answer.display || '',
465
- feedback: answer.feedback || '',
466
- expand: false,
467
- id: Crypto.id()
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
- // Add new answers with adjusted bucket indices
486
- newAnswers.forEach((bucketAnswers, index) => {
487
- const adjustedIndex = existingBucketCount + index
488
- if (!this.block.metadata.config.bucket_answers[adjustedIndex]) {
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
- // Update title and instructions if provided and we're in replace mode
506
- if (replaceMode) {
507
- if (activityData.metadata.config.title) {
508
- this.block.metadata.config.title = activityData.metadata.config.title
509
- }
494
+ if (activityData.metadata.config.instructions) {
495
+ this.block.metadata.config.instructions =
496
+ activityData.metadata.config.instructions
497
+ }
510
498
 
511
- if (activityData.metadata.config.instructions) {
512
- this.block.metadata.config.instructions = activityData.metadata.config.instructions
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
- // Update feedback messages if provided
516
- if (activityData.metadata.config.feedback_correct) {
517
- this.block.metadata.config.feedback_correct = activityData.metadata.config.feedback_correct
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
- if (activityData.metadata.config.feedback_incorrect) {
521
- this.block.metadata.config.feedback_incorrect = activityData.metadata.config.feedback_incorrect
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
- replaceMode
527
- ? this.$t('windward.games.components.settings.bucket_game.form.replaced_successfully')
528
- : this.$t('windward.games.components.settings.bucket_game.form.added_successfully'),
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(this.$t('windward.games.components.settings.bucket_game.form.invalid_response'), {
533
- duration: 5000
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(`${this.$t('windward.games.components.settings.bucket_game.form.failed_to_process')}: ${errorMessage}`, {
540
- duration: 5000
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
- <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>