@windward/games 0.22.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 +10 -0
- package/components/content/blocks/multipleChoice/MultipleChoice.vue +8 -1
- 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 +114 -49
- package/i18n/en-US/components/settings/multiple_choice.ts +4 -0
- package/i18n/es-ES/components/settings/multiple_choice.ts +4 -0
- package/i18n/sv-SE/components/settings/multiple_choice.ts +4 -0
- package/package.json +1 -1
- package/plugin.js +1 -1
|
@@ -82,14 +82,18 @@
|
|
|
82
82
|
<v-container class="pa-4 mb-6">
|
|
83
83
|
<v-row>
|
|
84
84
|
<v-col cols="12">
|
|
85
|
-
<
|
|
86
|
-
|
|
87
|
-
:
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
85
|
+
<PluginRef
|
|
86
|
+
target="contentBlockSettingTool"
|
|
87
|
+
:attrs="{
|
|
88
|
+
value: block,
|
|
89
|
+
course: course,
|
|
90
|
+
content: currentContent,
|
|
91
|
+
}"
|
|
92
|
+
:on="{
|
|
93
|
+
input: onPluginSetBlock,
|
|
94
|
+
append: onPluginAppendBlock,
|
|
95
|
+
}"
|
|
96
|
+
></PluginRef>
|
|
93
97
|
</v-col>
|
|
94
98
|
</v-row>
|
|
95
99
|
</v-container>
|
|
@@ -107,16 +111,20 @@
|
|
|
107
111
|
<script>
|
|
108
112
|
import _ from 'lodash'
|
|
109
113
|
import { mapGetters } from 'vuex'
|
|
110
|
-
import { GenerateAIQuestionButton } from '@windward/core/utils'
|
|
111
114
|
import BaseContentSettings from '~/components/Content/Settings/BaseContentSettings.js'
|
|
112
115
|
import BaseContentBlockSettings from '~/components/Content/Settings/BaseContentBlockSettings.vue'
|
|
113
116
|
import SortableExpansionPanel from '~/components/Core/SortableExpansionPanel.vue'
|
|
117
|
+
import PluginRef from '~/components/Core/PluginRef.vue'
|
|
114
118
|
import Uuid from '~/helpers/Uuid'
|
|
115
119
|
|
|
116
120
|
export default {
|
|
117
121
|
name: 'SortingGameSettingsManager',
|
|
118
122
|
extends: BaseContentSettings,
|
|
119
|
-
components: {
|
|
123
|
+
components: {
|
|
124
|
+
SortableExpansionPanel,
|
|
125
|
+
BaseContentBlockSettings,
|
|
126
|
+
PluginRef,
|
|
127
|
+
},
|
|
120
128
|
beforeMount() {
|
|
121
129
|
if (_.isEmpty(this.block)) {
|
|
122
130
|
this.block = {}
|
|
@@ -202,79 +210,116 @@ export default {
|
|
|
202
210
|
return (element.id = startingIndex)
|
|
203
211
|
})
|
|
204
212
|
},
|
|
205
|
-
|
|
213
|
+
onPluginSetBlock(activityData) {
|
|
206
214
|
this.loading = true
|
|
207
215
|
try {
|
|
208
216
|
// Process the activity data
|
|
209
|
-
if (
|
|
217
|
+
if (
|
|
218
|
+
activityData &&
|
|
219
|
+
activityData.metadata &&
|
|
210
220
|
activityData.metadata.config &&
|
|
211
221
|
activityData.metadata.config.answer &&
|
|
212
|
-
Array.isArray(activityData.metadata.config.answer)
|
|
213
|
-
|
|
222
|
+
Array.isArray(activityData.metadata.config.answer)
|
|
223
|
+
) {
|
|
214
224
|
// Save new items
|
|
215
225
|
const newItems = activityData.metadata.config.answer
|
|
216
226
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
227
|
+
// Replace mode: Clear existing items
|
|
228
|
+
this.block.metadata.config.answer.splice(
|
|
229
|
+
0,
|
|
230
|
+
this.block.metadata.config.answer.length
|
|
231
|
+
)
|
|
220
232
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
})
|
|
233
|
+
// Add all new items - ensure they have the correct structure
|
|
234
|
+
newItems.forEach((item, index) => {
|
|
235
|
+
this.block.metadata.config.answer.push({
|
|
236
|
+
id: index,
|
|
237
|
+
value: item.value || '',
|
|
238
|
+
expand: false,
|
|
228
239
|
})
|
|
229
|
-
}
|
|
230
|
-
// Merge mode: Add new items to existing ones
|
|
231
|
-
const hasOnlyEmptyAnswer = this.block.metadata.config.answer.length === 1 &&
|
|
232
|
-
this.block.metadata.config.answer[0].value === ''
|
|
233
|
-
|
|
234
|
-
if (hasOnlyEmptyAnswer) {
|
|
235
|
-
// If there's only one empty answer, replace it instead of merging
|
|
236
|
-
this.block.metadata.config.answer.splice(0, 1)
|
|
237
|
-
}
|
|
240
|
+
})
|
|
238
241
|
|
|
239
|
-
|
|
242
|
+
// Update title and instructions if provided and we're in replace mode
|
|
240
243
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
value: item.value || '',
|
|
245
|
-
expand: false,
|
|
246
|
-
})
|
|
247
|
-
currentId += 1
|
|
248
|
-
})
|
|
244
|
+
if (activityData.metadata.config.title) {
|
|
245
|
+
this.block.metadata.config.title =
|
|
246
|
+
activityData.metadata.config.title
|
|
249
247
|
}
|
|
250
248
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
249
|
+
if (activityData.metadata.config.instructions) {
|
|
250
|
+
this.block.metadata.config.instructions =
|
|
251
|
+
activityData.metadata.config.instructions
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// Update feedback if provided
|
|
255
|
+
if (activityData.metadata.config.feedback_correct) {
|
|
256
|
+
this.block.metadata.config.feedback_correct =
|
|
257
|
+
activityData.metadata.config.feedback_correct
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
this.$toast.success(
|
|
261
|
+
this.$t(
|
|
262
|
+
'windward.games.components.settings.sorting_game.form.replaced_successfully'
|
|
263
|
+
),
|
|
264
|
+
|
|
265
|
+
{ duration: 3000 }
|
|
266
|
+
)
|
|
267
|
+
} else {
|
|
268
|
+
throw new Error('activity.error.technical')
|
|
269
|
+
}
|
|
270
|
+
} catch (error) {
|
|
271
|
+
// Let the error bubble up to Plugin with proper error type
|
|
272
|
+
throw error
|
|
273
|
+
} finally {
|
|
274
|
+
this.loading = false
|
|
275
|
+
}
|
|
276
|
+
},
|
|
277
|
+
onPluginAppendBlock(activityData) {
|
|
278
|
+
this.loading = true
|
|
279
|
+
try {
|
|
280
|
+
// Process the activity data
|
|
281
|
+
if (
|
|
282
|
+
activityData &&
|
|
283
|
+
activityData.metadata &&
|
|
284
|
+
activityData.metadata.config &&
|
|
285
|
+
activityData.metadata.config.answer &&
|
|
286
|
+
Array.isArray(activityData.metadata.config.answer)
|
|
287
|
+
) {
|
|
288
|
+
// Save new items
|
|
289
|
+
const newItems = activityData.metadata.config.answer
|
|
256
290
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
291
|
+
// Merge mode: Add new items to existing ones
|
|
292
|
+
const hasOnlyEmptyAnswer =
|
|
293
|
+
this.block.metadata.config.answer.length === 1 &&
|
|
294
|
+
this.block.metadata.config.answer[0].value === ''
|
|
260
295
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
}
|
|
296
|
+
if (hasOnlyEmptyAnswer) {
|
|
297
|
+
// If there's only one empty answer, replace it instead of merging
|
|
298
|
+
this.block.metadata.config.answer.splice(0, 1)
|
|
265
299
|
}
|
|
266
300
|
|
|
301
|
+
let currentId = this.block.metadata.config.answer.length
|
|
302
|
+
|
|
303
|
+
newItems.forEach((item) => {
|
|
304
|
+
this.block.metadata.config.answer.push({
|
|
305
|
+
id: currentId,
|
|
306
|
+
value: item.value || '',
|
|
307
|
+
expand: false,
|
|
308
|
+
})
|
|
309
|
+
currentId += 1
|
|
310
|
+
})
|
|
311
|
+
|
|
267
312
|
this.$toast.success(
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
313
|
+
this.$t(
|
|
314
|
+
'windward.games.components.settings.sorting_game.form.added_successfully'
|
|
315
|
+
),
|
|
271
316
|
{ duration: 3000 }
|
|
272
317
|
)
|
|
273
318
|
} else {
|
|
274
319
|
throw new Error('activity.error.technical')
|
|
275
320
|
}
|
|
276
321
|
} catch (error) {
|
|
277
|
-
// Let the error bubble up to
|
|
322
|
+
// Let the error bubble up to Plugin with proper error type
|
|
278
323
|
throw error
|
|
279
324
|
} finally {
|
|
280
325
|
this.loading = false
|
|
@@ -122,14 +122,18 @@
|
|
|
122
122
|
<v-container class="pa-4 mb-6">
|
|
123
123
|
<v-row>
|
|
124
124
|
<v-col cols="12">
|
|
125
|
-
<
|
|
126
|
-
|
|
127
|
-
:
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
125
|
+
<PluginRef
|
|
126
|
+
target="contentBlockSettingTool"
|
|
127
|
+
:attrs="{
|
|
128
|
+
value: block,
|
|
129
|
+
course: course,
|
|
130
|
+
content: currentContent,
|
|
131
|
+
}"
|
|
132
|
+
:on="{
|
|
133
|
+
input: onPluginSetBlock,
|
|
134
|
+
append: onPluginAppendBlock,
|
|
135
|
+
}"
|
|
136
|
+
></PluginRef>
|
|
133
137
|
</v-col>
|
|
134
138
|
</v-row>
|
|
135
139
|
</v-container>
|
|
@@ -138,10 +142,10 @@
|
|
|
138
142
|
<script>
|
|
139
143
|
import _ from 'lodash'
|
|
140
144
|
import { mapGetters } from 'vuex'
|
|
141
|
-
import { GenerateAIQuestionButton } from '@windward/core/utils'
|
|
142
145
|
import BaseContentSettings from '~/components/Content/Settings/BaseContentSettings.js'
|
|
143
146
|
import SortableExpansionPanel from '~/components/Core/SortableExpansionPanel.vue'
|
|
144
147
|
import BaseContentBlockSettings from '~/components/Content/Settings/BaseContentBlockSettings.vue'
|
|
148
|
+
import PluginRef from '~/components/Core/PluginRef.vue'
|
|
145
149
|
|
|
146
150
|
export default {
|
|
147
151
|
name: 'WordJumbleSettings',
|
|
@@ -149,7 +153,7 @@ export default {
|
|
|
149
153
|
components: {
|
|
150
154
|
SortableExpansionPanel,
|
|
151
155
|
BaseContentBlockSettings,
|
|
152
|
-
|
|
156
|
+
PluginRef,
|
|
153
157
|
},
|
|
154
158
|
beforeMount() {
|
|
155
159
|
if (_.isEmpty(this.block)) {
|
|
@@ -194,7 +198,6 @@ export default {
|
|
|
194
198
|
}
|
|
195
199
|
},
|
|
196
200
|
computed: {
|
|
197
|
-
|
|
198
201
|
...mapGetters({
|
|
199
202
|
course: 'course/get',
|
|
200
203
|
currentContent: 'content/get',
|
|
@@ -251,69 +254,131 @@ export default {
|
|
|
251
254
|
this.block.metadata.config.currentWord =
|
|
252
255
|
this.block.metadata.config.words.length - 1
|
|
253
256
|
},
|
|
254
|
-
|
|
257
|
+
onPluginSetBlock(activityData) {
|
|
255
258
|
this.loading = true
|
|
256
259
|
try {
|
|
257
260
|
// Process the activity data
|
|
258
|
-
if (
|
|
261
|
+
if (
|
|
262
|
+
activityData &&
|
|
263
|
+
activityData.metadata &&
|
|
259
264
|
activityData.metadata.config &&
|
|
260
265
|
activityData.metadata.config.words &&
|
|
261
|
-
Array.isArray(activityData.metadata.config.words)
|
|
262
|
-
|
|
266
|
+
Array.isArray(activityData.metadata.config.words)
|
|
267
|
+
) {
|
|
263
268
|
const newWords = activityData.metadata.config.words
|
|
264
269
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
this.
|
|
277
|
-
id: this.block.metadata.config.words.length + 1,
|
|
278
|
-
value: word.value || '',
|
|
279
|
-
hint: word.hint || '',
|
|
280
|
-
shuffledWord: this.shuffle(word.value || '')
|
|
281
|
-
})
|
|
270
|
+
this.block.metadata.config.words.splice(
|
|
271
|
+
0,
|
|
272
|
+
this.block.metadata.config.words.length
|
|
273
|
+
)
|
|
274
|
+
newWords.forEach((word) => {
|
|
275
|
+
this.block.metadata.config.words.push({
|
|
276
|
+
id:
|
|
277
|
+
word.id ||
|
|
278
|
+
this.block.metadata.config.words.length + 1,
|
|
279
|
+
value: word.value || '',
|
|
280
|
+
hint: word.hint || '',
|
|
281
|
+
shuffledWord: this.shuffle(word.value || ''),
|
|
282
282
|
})
|
|
283
|
+
})
|
|
284
|
+
|
|
285
|
+
if (activityData.metadata.config.title) {
|
|
286
|
+
this.block.metadata.config.title =
|
|
287
|
+
activityData.metadata.config.title
|
|
283
288
|
}
|
|
284
289
|
|
|
285
|
-
if (
|
|
286
|
-
this.block.metadata.config.
|
|
290
|
+
if (activityData.metadata.config.feedback_correct) {
|
|
291
|
+
this.block.metadata.config.feedback_correct =
|
|
292
|
+
activityData.metadata.config.feedback_correct
|
|
287
293
|
}
|
|
288
294
|
|
|
289
|
-
if (
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
295
|
+
if (activityData.metadata.config.feedback_incorrect) {
|
|
296
|
+
this.block.metadata.config.feedback_incorrect =
|
|
297
|
+
activityData.metadata.config.feedback_incorrect
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
this.block.metadata.config.currentWord = 0
|
|
293
301
|
|
|
294
|
-
|
|
295
|
-
|
|
302
|
+
this.$toast.success(
|
|
303
|
+
this.$t(
|
|
304
|
+
'windward.games.components.settings.word_jumble.form.replaced_successfully'
|
|
305
|
+
),
|
|
306
|
+
{ duration: 3000 }
|
|
307
|
+
)
|
|
308
|
+
} else {
|
|
309
|
+
this.$toast.error(
|
|
310
|
+
this.$t(
|
|
311
|
+
'windward.games.components.settings.word_jumble.form.invalid_response'
|
|
312
|
+
),
|
|
313
|
+
{
|
|
314
|
+
duration: 5000,
|
|
296
315
|
}
|
|
316
|
+
)
|
|
317
|
+
}
|
|
318
|
+
} catch (error) {
|
|
319
|
+
const errorMessage = error.message || 'Unknown error occurred'
|
|
320
|
+
this.$toast.error(
|
|
321
|
+
`${this.$t(
|
|
322
|
+
'windward.games.components.settings.word_jumble.form.failed_to_process'
|
|
323
|
+
)}: ${errorMessage}`,
|
|
324
|
+
{
|
|
325
|
+
duration: 5000,
|
|
297
326
|
}
|
|
327
|
+
)
|
|
328
|
+
} finally {
|
|
329
|
+
this.loading = false
|
|
330
|
+
}
|
|
331
|
+
},
|
|
332
|
+
onPluginAppendBlock(activityData) {
|
|
333
|
+
this.loading = true
|
|
334
|
+
try {
|
|
335
|
+
// Process the activity data
|
|
336
|
+
if (
|
|
337
|
+
activityData &&
|
|
338
|
+
activityData.metadata &&
|
|
339
|
+
activityData.metadata.config &&
|
|
340
|
+
activityData.metadata.config.words &&
|
|
341
|
+
Array.isArray(activityData.metadata.config.words)
|
|
342
|
+
) {
|
|
343
|
+
const newWords = activityData.metadata.config.words
|
|
344
|
+
|
|
345
|
+
newWords.forEach((word) => {
|
|
346
|
+
this.block.metadata.config.words.push({
|
|
347
|
+
id: this.block.metadata.config.words.length + 1,
|
|
348
|
+
value: word.value || '',
|
|
349
|
+
hint: word.hint || '',
|
|
350
|
+
shuffledWord: this.shuffle(word.value || ''),
|
|
351
|
+
})
|
|
352
|
+
})
|
|
298
353
|
|
|
299
354
|
this.block.metadata.config.currentWord = 0
|
|
300
355
|
|
|
301
356
|
this.$toast.success(
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
357
|
+
this.$t(
|
|
358
|
+
'windward.games.components.settings.word_jumble.form.added_successfully'
|
|
359
|
+
),
|
|
305
360
|
{ duration: 3000 }
|
|
306
361
|
)
|
|
307
362
|
} else {
|
|
308
|
-
this.$toast.error(
|
|
309
|
-
|
|
310
|
-
|
|
363
|
+
this.$toast.error(
|
|
364
|
+
this.$t(
|
|
365
|
+
'windward.games.components.settings.word_jumble.form.invalid_response'
|
|
366
|
+
),
|
|
367
|
+
{
|
|
368
|
+
duration: 5000,
|
|
369
|
+
}
|
|
370
|
+
)
|
|
311
371
|
}
|
|
312
372
|
} catch (error) {
|
|
313
373
|
const errorMessage = error.message || 'Unknown error occurred'
|
|
314
|
-
this.$toast.error(
|
|
315
|
-
|
|
316
|
-
|
|
374
|
+
this.$toast.error(
|
|
375
|
+
`${this.$t(
|
|
376
|
+
'windward.games.components.settings.word_jumble.form.failed_to_process'
|
|
377
|
+
)}: ${errorMessage}`,
|
|
378
|
+
{
|
|
379
|
+
duration: 5000,
|
|
380
|
+
}
|
|
381
|
+
)
|
|
317
382
|
} finally {
|
|
318
383
|
this.loading = false
|
|
319
384
|
}
|
|
@@ -15,4 +15,8 @@ export default {
|
|
|
15
15
|
add_answer: 'Add Answer Option',
|
|
16
16
|
add_question: 'Add Question',
|
|
17
17
|
answer: 'Answers',
|
|
18
|
+
added_successfully: 'Questions added successfully',
|
|
19
|
+
replaced_successfully: 'Questions replaced successfully',
|
|
20
|
+
invalid_response: 'Could not process AI response for multiple-choice.',
|
|
21
|
+
failed_to_process: 'Failed to process AI response',
|
|
18
22
|
}
|
|
@@ -15,4 +15,8 @@ export default {
|
|
|
15
15
|
add_answer: 'Agregar opción de respuesta',
|
|
16
16
|
add_question: 'Agregar pregunta',
|
|
17
17
|
answer: 'Respuestas',
|
|
18
|
+
added_successfully: 'Preguntas agregadas correctamente',
|
|
19
|
+
replaced_successfully: 'Preguntas reemplazadas correctamente',
|
|
20
|
+
invalid_response: 'No se pudo procesar la respuesta de IA para opción múltiple.',
|
|
21
|
+
failed_to_process: 'No se pudo procesar la respuesta de IA',
|
|
18
22
|
}
|
|
@@ -14,4 +14,8 @@ export default {
|
|
|
14
14
|
add_answer: 'Lägg till svarsalternativ',
|
|
15
15
|
add_question: 'Lägg till fråga',
|
|
16
16
|
answer: 'Svar',
|
|
17
|
+
added_successfully: 'Frågor har lagts till',
|
|
18
|
+
replaced_successfully: 'Frågor har ersatts',
|
|
19
|
+
invalid_response: 'Kunde inte bearbeta AI-svar för flervalsfrågor.',
|
|
20
|
+
failed_to_process: 'Misslyckades med att bearbeta AI-svar',
|
|
17
21
|
}
|
package/package.json
CHANGED