@windward/games 0.2.2 → 0.4.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.
Files changed (41) hide show
  1. package/components/content/CrudTable.vue +8 -4
  2. package/components/content/DatableEditor.vue +1 -0
  3. package/components/content/blocks/crosswordPuzzle/CrosswordPuzzle.vue +2 -1
  4. package/components/content/blocks/dragDrop/BucketGame.vue +4 -3
  5. package/components/content/blocks/dragDrop/SortingGame.vue +37 -28
  6. package/components/content/blocks/flashcards/CardFace.vue +48 -9
  7. package/components/content/blocks/flashcards/Flashcard.vue +26 -17
  8. package/components/content/blocks/flashcards/FlashcardSlides.vue +10 -5
  9. package/components/content/blocks/matchingGame/MatchingGame.vue +76 -50
  10. package/components/content/blocks/multipleChoice/MultipleChoice.vue +13 -9
  11. package/components/content/blocks/multipleChoice/QuestionDialog.vue +27 -13
  12. package/components/content/blocks/quizshowGame/AnswerPanel.vue +2 -1
  13. package/components/content/blocks/quizshowGame/Gridview.vue +2 -1
  14. package/components/content/blocks/quizshowGame/QuizShow.vue +5 -2
  15. package/components/content/blocks/sevenStrikes/SevenStikes.vue +8 -2
  16. package/components/content/blocks/slideshow/SlideShow.vue +31 -22
  17. package/components/content/blocks/wordJumble/WordJumble.vue +8 -2
  18. package/components/settings/BucketGameSettingsManager.vue +25 -5
  19. package/components/settings/CrosswordPuzzleSettingsManager.vue +20 -10
  20. package/components/settings/FlashCardSlidesManager.vue +194 -115
  21. package/components/settings/MatchingGameManager.vue +57 -8
  22. package/components/settings/MultipleChoiceSettingsManager.vue +33 -77
  23. package/components/settings/QuizShowSettingsManager.vue +22 -11
  24. package/components/settings/SevenStrikesSettingsManager.vue +17 -5
  25. package/components/settings/SlideShowManager.vue +46 -15
  26. package/components/settings/SortingGameSettingsManager.vue +19 -8
  27. package/components/settings/WordJumbleSettingsManager.vue +22 -10
  28. package/i18n/en-US/components/content/blocks/slideshow.ts +1 -3
  29. package/i18n/en-US/components/settings/seven_strikes.ts +1 -1
  30. package/i18n/es-ES/components/content/blocks/slideshow.ts +0 -2
  31. package/i18n/es-ES/components/settings/seven_strikes.ts +1 -1
  32. package/i18n/sv-SE/components/content/blocks/slideshow.ts +0 -2
  33. package/i18n/sv-SE/components/settings/seven_strikes.ts +1 -1
  34. package/jest.config.js +0 -1
  35. package/package.json +2 -2
  36. package/test/__mocks__/componentsMock.js +3 -1
  37. package/test/__mocks__/modelMock.js +13 -84
  38. package/test/blocks/flashcards/CardFace.spec.js +2 -0
  39. package/test/blocks/flashcards/Flashcard.spec.js +1 -0
  40. package/test/blocks/multipleChoice/MultipleChoice.spec.js +1 -1
  41. package/test/settings/WordJumbleManager.spec.js +3 -0
@@ -11,7 +11,7 @@
11
11
  <v-toolbar-title> {{ title }}</v-toolbar-title>
12
12
  <v-divider class="mx-4" inset vertical></v-divider>
13
13
  <v-spacer></v-spacer>
14
- <v-btn color="primary" dark class="mb-2" @click="addNew">
14
+ <v-btn color="primary" elevation="0" dark class="mb-2" @click="addNew">
15
15
  {{
16
16
  $t(
17
17
  'windward.games.components.content.crud_table.add_row'
@@ -27,6 +27,7 @@
27
27
  <template #activator="{ on, attrs }">
28
28
  <v-btn
29
29
  color="primary"
30
+ elevation="0"
30
31
  dark
31
32
  class="mb-2"
32
33
  v-bind="attrs"
@@ -71,12 +72,13 @@
71
72
  <v-spacer></v-spacer>
72
73
  <v-btn
73
74
  color="blue darken-1"
75
+ elevation="0"
74
76
  text
75
77
  @click="close"
76
78
  >
77
79
  {{ $t('shared.forms.cancel') }}
78
80
  </v-btn>
79
- <v-btn color="blue darken-1" text @click="save">
81
+ <v-btn color="blue darken-1" elevation="0" text @click="save">
80
82
  {{ $t('shared.forms.save') }}
81
83
  </v-btn>
82
84
  </v-card-actions>
@@ -91,12 +93,14 @@
91
93
  <v-spacer></v-spacer>
92
94
  <v-btn
93
95
  color="blue darken-1"
96
+ elevation="0"
94
97
  text
95
98
  @click="closeDelete"
96
99
  >{{ $t('shared.forms.cancel') }}
97
100
  </v-btn>
98
101
  <v-btn
99
102
  color="blue darken-1"
103
+ elevation="0"
100
104
  text
101
105
  @click="deleteItemConfirm"
102
106
  >{{ $t('shared.forms.confirm') }}
@@ -127,7 +131,7 @@
127
131
  @input="onDropCallback"
128
132
  >
129
133
  <template #item.actions="{ item }">
130
- <v-btn outlined v-if="useModal">
134
+ <v-btn outlined elevation="0" v-if="useModal">
131
135
  <span class="sr-only">
132
136
  {{ $t('shared.forms.edit') }}</span
133
137
  >
@@ -139,7 +143,7 @@
139
143
  mdi-pencil
140
144
  </v-icon>
141
145
  </v-btn>
142
- <v-btn outlined>
146
+ <v-btn outlined elevation="0">
143
147
  <span class="sr-only">
144
148
  {{ $t('shared.forms.delete') }}</span
145
149
  >
@@ -25,6 +25,7 @@
25
25
  ></v-text-field>-->
26
26
  <v-btn
27
27
  color="primary"
28
+ elevation="0"
28
29
  class="col-md-12 white--text"
29
30
  @click="addNew"
30
31
  >
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <v-container>
3
3
  <div>
4
- <h3>{{ block.metadata.config.title }}</h3>
4
+ <h2>{{ block.metadata.config.title }}</h2>
5
5
  <p>{{ block.metadata.config.instructions }}</p>
6
6
  </div>
7
7
  <v-alert v-if="wordMap.length === 0" type="info" class="text-center">
@@ -86,6 +86,7 @@
86
86
  <v-col cols="12" class="d-flex justify-center">
87
87
  <v-btn
88
88
  color="primary"
89
+ elevation="0"
89
90
  outlined
90
91
  class="ma-3"
91
92
  @click="onSetUpData"
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <div>
3
3
  <div>
4
- <h3
4
+ <h2
5
5
  :aria-label="
6
6
  $t(
7
7
  'windward.games.components.content.blocks.bucket_game.aria_title'
@@ -10,7 +10,7 @@
10
10
  tabindex="0"
11
11
  >
12
12
  {{ block.metadata.config.title }}
13
- </h3>
13
+ </h2>
14
14
 
15
15
  <p tabindex="0">
16
16
  {{ block.metadata.config.instructions }}
@@ -37,6 +37,7 @@
37
37
  v-if="status === 'successOutline'"
38
38
  class="mr-5"
39
39
  color="success"
40
+ elevation="0"
40
41
  @click="continueGame"
41
42
  >{{ $t('shared.forms.continue') }}
42
43
  </v-btn>
@@ -232,7 +233,7 @@
232
233
  style="pointer-events: none"
233
234
  ></v-progress-linear>
234
235
  <br />
235
- <v-btn color="primary" outlined @click="onReset"
236
+ <v-btn color="primary" outlined elevation="0" @click="onReset"
236
237
  >{{ $t('shared.forms.reset') }}
237
238
  </v-btn>
238
239
  </v-col>
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div>
3
- <h3>{{ block.metadata.config.title }}</h3>
3
+ <h2>{{ block.metadata.config.title }}</h2>
4
4
  <p>
5
5
  {{ block.metadata.config.instructions }}
6
6
  </p>
@@ -16,12 +16,12 @@
16
16
  }}</v-col>
17
17
  <v-col cols="2">
18
18
  <v-row
19
- v-if="isFail() || isSuccess()"
19
+ v-if="onFail() || onSuccess()"
20
20
  class="d-flex justify-end"
21
21
  >
22
22
  <v-container
23
- v-if="isFail()"
24
- @click="continueGame"
23
+ v-if="onFail()"
24
+ @click="onContinueGame"
25
25
  class="d-flex justify-end"
26
26
  ><v-icon class="icon--error"
27
27
  >mdi-close-circle</v-icon
@@ -40,7 +40,7 @@
40
40
  v-bind="dragOptions"
41
41
  @change="onDragChange"
42
42
  >
43
- <v-row v-for="index in input.length" :key="'bucket_' + index">
43
+ <v-row v-for="index in input.length" :key="'sortable_' + index">
44
44
  <v-col cols="1" md="1" class="d-flex justify-end pa-0">
45
45
  <v-icon v-if="success[index - 1]" class="icon--success"
46
46
  >mdi-check-circle
@@ -53,7 +53,7 @@
53
53
  <v-card
54
54
  :class="
55
55
  'pa-2 flex-fill container-outline ' +
56
- bucketStateClass(index)
56
+ sortableStateClass(index)
57
57
  "
58
58
  outlined
59
59
  tile
@@ -69,11 +69,15 @@
69
69
  </draggable>
70
70
  <v-container class="mt-3">
71
71
  <v-row
72
- v-if="!isFail() && !isSuccess()"
72
+ v-if="!onFail() && !onSuccess()"
73
73
  class="d-flex justify-center"
74
74
  >
75
75
  <v-spacer class="col-lg-1" />
76
- <v-btn color="primary" elevation="0" @click="checkAnswers">
76
+ <v-btn
77
+ color="primary"
78
+ elevation="0"
79
+ @click="onCheckAnswers"
80
+ >
77
81
  {{
78
82
  $t(
79
83
  'windward.games.components.content.blocks.sorting_game.check_answers'
@@ -82,17 +86,22 @@
82
86
  </v-btn>
83
87
  </v-row>
84
88
  <v-row
85
- v-if="isFail() || isSuccess()"
89
+ v-if="onFail() || onSuccess()"
86
90
  class="d-flex justify-center"
87
91
  >
88
92
  <v-btn
89
- v-if="isFail()"
93
+ v-if="onFail()"
90
94
  color="primary"
95
+ elevation="0"
91
96
  text
92
- @click="continueGame"
97
+ @click="onContinueGame"
93
98
  >{{ $t('shared.forms.try_again') }} </v-btn
94
99
  >&nbsp;&nbsp;
95
- <v-btn color="primary" elevation="0" @click="reset" outlined
100
+ <v-btn
101
+ color="primary"
102
+ elevation="0"
103
+ @click="onReset"
104
+ outlined
96
105
  >{{ $t('shared.forms.reset') }}
97
106
  </v-btn>
98
107
  </v-row>
@@ -110,7 +119,7 @@
110
119
  <v-row
111
120
  class="justify-center align-center"
112
121
  v-for="index in block.metadata.config.answer.length"
113
- :key="'bucket_' + index"
122
+ :key="'sortable_' + index"
114
123
  >
115
124
  <v-col cols="1" v-if="graded">
116
125
  <v-icon v-if="success[index - 1]" color="success"
@@ -124,7 +133,7 @@
124
133
  <v-card
125
134
  :class="
126
135
  'pa-2 flex-fill container-outline ' +
127
- bucketStateClass(index)
136
+ sortableStateClass(index)
128
137
  "
129
138
  elevation="0"
130
139
  outlined
@@ -253,7 +262,7 @@ export default {
253
262
  resolve(true)
254
263
  })
255
264
  },
256
- reset() {
265
+ onReset() {
257
266
  this.disabled = false
258
267
  this.graded = false
259
268
  this.success = []
@@ -264,7 +273,7 @@ export default {
264
273
  this.feedback = this.block.metadata.config.feedback_default
265
274
  this.seed = Math.floor(Math.random() * 100)
266
275
  },
267
- continueGame() {
276
+ onContinueGame() {
268
277
  this.disabled = false
269
278
  this.graded = false
270
279
  this.success = []
@@ -272,7 +281,7 @@ export default {
272
281
  this.feedback = this.block.metadata.config.feedback_default
273
282
  this.seed = Math.floor(Math.random() * 100)
274
283
  },
275
- isSuccess() {
284
+ onSuccess() {
276
285
  let result = false
277
286
  let successCounter = 0
278
287
  this.success.forEach(function (item) {
@@ -285,7 +294,7 @@ export default {
285
294
  }
286
295
  return result
287
296
  },
288
- isFail() {
297
+ onFail() {
289
298
  let result = false
290
299
  this.fail.forEach(function (item) {
291
300
  if (item === true) {
@@ -296,15 +305,15 @@ export default {
296
305
  },
297
306
  feedbackClass() {
298
307
  let result = ''
299
- if (this.isSuccess()) {
308
+ if (this.onSuccess()) {
300
309
  result = 'container-feedback-success '
301
310
  }
302
- if (this.isFail()) {
311
+ if (this.onFail()) {
303
312
  result = 'container-feedback-error '
304
313
  }
305
314
  return result
306
315
  },
307
- checkAnswers() {
316
+ onCheckAnswers() {
308
317
  const self = this
309
318
  this.disabled = true
310
319
 
@@ -318,22 +327,22 @@ export default {
318
327
  }
319
328
  })
320
329
 
321
- if (this.isSuccess()) {
330
+ if (this.onSuccess()) {
322
331
  this.feedback = this.block.metadata.config.feedback_correct
323
332
  this.emitCompleted()
324
333
  }
325
- if (this.isFail()) {
334
+ if (this.onFail()) {
326
335
  this.feedback = this.block.metadata.config.feedback_incorrect
327
336
  }
328
337
  this.graded = true
329
338
  this.seed = Math.floor(Math.random() * 100)
330
339
  },
331
- bucketStateClass(index) {
340
+ sortableStateClass(index) {
332
341
  if (this.success[index - 1]) {
333
- return 'bucket--success'
342
+ return 'sortable--success'
334
343
  }
335
344
  if (this.fail[index - 1]) {
336
- return 'bucket--error'
345
+ return 'sortable--error'
337
346
  }
338
347
  return ''
339
348
  },
@@ -356,11 +365,11 @@ export default {
356
365
  border: 4px solid var(--v-error-base);
357
366
  color: var(--v-error-base);
358
367
  }
359
- .bucket--error {
368
+ .sortable--error {
360
369
  background-color: var(--v-error-base);
361
370
  color: white;
362
371
  }
363
- .bucket--success {
372
+ .sortable--success {
364
373
  background-color: var(--v-success-base);
365
374
  color: white;
366
375
  }
@@ -7,16 +7,16 @@
7
7
  </v-row>
8
8
  <br />
9
9
  <v-row
10
+ v-if="imagePublicUrl"
10
11
  no-gutters
11
12
  align="center"
12
13
  justify="center"
13
- v-if="settings.img !== ''"
14
14
  >
15
15
  <v-img
16
16
  contain
17
17
  :aspect-ratio="16 / 9"
18
- :src="settings.img"
19
- :alt="settings.altText"
18
+ :src="imagePublicUrl"
19
+ :alt="imageAlt"
20
20
  max-height="210"
21
21
  max-width="600"
22
22
  />
@@ -31,19 +31,22 @@
31
31
  </template>
32
32
 
33
33
  <script>
34
+ import _ from 'lodash'
34
35
  import { MathHelper, ContentViewer } from '@windward/core/utils'
36
+ import Uuid from '~/helpers/Uuid'
35
37
 
36
38
  export default {
37
39
  name: 'CardFace',
38
40
  components: { ContentViewer },
39
41
  props: {
40
- settings: { type: Object },
41
- side: { type: String },
42
+ settings: { type: Object, required: true },
43
+ side: { type: String, required: true },
44
+ assets: { type: Array, required: true },
42
45
  },
43
46
  computed: {
44
47
  textClass() {
45
48
  if (
46
- !this.settings.img &&
49
+ !this.settings.imageAsset &&
47
50
  this.settings.text &&
48
51
  this.settings.text.length < 100 &&
49
52
  this.side === 'front'
@@ -55,7 +58,7 @@ export default {
55
58
  return 'text-center card-content--bold'
56
59
  }
57
60
  if (
58
- !this.settings.img &&
61
+ !this.settings.imageAsset &&
59
62
  this.settings.text &&
60
63
  (MathHelper.containsMathML(this.settings.text.length) ||
61
64
  MathHelper.containsLatex(this.settings.text.length))
@@ -63,11 +66,47 @@ export default {
63
66
  return 'text-justify centered'
64
67
  }
65
68
 
66
-
67
69
  return 'px-6 text-justify'
68
70
  },
71
+ imageAsset() {
72
+ if (!this.settings.imageAsset) {
73
+ return null
74
+ }
75
+
76
+ let image = _.cloneDeep(this.settings.imageAsset)
77
+
78
+ // If the file is linked then resolve it first
79
+ // Otherwise it's a hard link that we can just return
80
+ if (image && image.file_asset_id !== null) {
81
+ image = this.getAssetByFileAssetId(image.file_asset_id)
82
+ }
83
+ return image
84
+ },
85
+ imagePublicUrl() {
86
+ return _.get(this.imageAsset, 'asset.public_url', '')
87
+ },
88
+ imageAlt() {
89
+ // Default to user defined alt but fallback to global alt
90
+ if (this.settings.imageAlt) {
91
+ return this.settings.imageAlt
92
+ } else {
93
+ return _.get(this.imageAsset, 'asset.metadata.props.alt', '')
94
+ }
95
+ },
96
+ },
97
+ methods: {
98
+ getAssetByFileAssetId(fileAssetId) {
99
+ // Not a uuid. Instant fail
100
+ if (!Uuid.test(fileAssetId)) {
101
+ return null
102
+ }
103
+ const foundAsset = this.assets.find((asset) => {
104
+ return _.get(asset, 'file_asset_id', null) === fileAssetId
105
+ })
106
+
107
+ return foundAsset || null
108
+ },
69
109
  },
70
- methods: {},
71
110
  }
72
111
  </script>
73
112
 
@@ -2,7 +2,11 @@
2
2
  <v-container style="height: 100%" class="div-container">
3
3
  <v-card outlined @click="toggleCard" v-show="value" :class="cardClass">
4
4
  <v-card-text>
5
- <card-face :settings="frontFace" side="front"></card-face>
5
+ <CardFace
6
+ side="front"
7
+ :settings="frontFace"
8
+ :assets="assets"
9
+ ></CardFace>
6
10
  </v-card-text>
7
11
  </v-card>
8
12
  <v-card outlined @click="toggleCard" v-show="!value" :class="cardClass">
@@ -12,7 +16,11 @@
12
16
  }}</v-row>
13
17
  </v-card-title>
14
18
  <v-card-text>
15
- <cardFace :settings="backFace" side="back"></cardFace>
19
+ <CardFace
20
+ side="back"
21
+ :settings="backFace"
22
+ :assets="assets"
23
+ ></CardFace>
16
24
  </v-card-text>
17
25
  </v-card>
18
26
  </v-container>
@@ -29,9 +37,10 @@ export default {
29
37
  }
30
38
  },
31
39
  props: {
40
+ value: { type: Boolean, required: false, default: false },
32
41
  options: { type: Object, default: {} },
33
42
  slide: { type: Number, required: true, default: 0 },
34
- value: { type: Boolean, required: false, default: false },
43
+ assets: { type: Array, required: true },
35
44
  },
36
45
 
37
46
  computed: {
@@ -41,11 +50,17 @@ export default {
41
50
  result = result + ' flipInY'
42
51
  }
43
52
 
44
- if (this.frontFace.img === '' && this.backFace.img === '') {
53
+ if (
54
+ this.frontFace.imageAsset === '' &&
55
+ this.backFace.imageAsset === ''
56
+ ) {
45
57
  result = result + ' flashcard--size-md'
46
58
  }
47
59
 
48
- if (this.frontFace.img !== '' || this.backFace.img !== '') {
60
+ if (
61
+ this.frontFace.imageAsset !== '' ||
62
+ this.backFace.imageAsset !== ''
63
+ ) {
49
64
  result = result + ' flashcard--size-lg'
50
65
  }
51
66
 
@@ -53,12 +68,9 @@ export default {
53
68
  },
54
69
  frontFace() {
55
70
  return {
56
- img:
57
- this.options.front.img && this.options.front.img.asset
58
- ? this.options.front.img.asset.public_url
59
- : '',
60
- altText: this.options.front.imgAltText
61
- ? this.options.front.imgAltText
71
+ imageAsset: this.options.front.imageAsset,
72
+ imageAlt: this.options.front.imageAlt
73
+ ? this.options.front.imageAlt
62
74
  : '',
63
75
  text: this.options.front.text,
64
76
  header: this.options.front.header,
@@ -69,12 +81,9 @@ export default {
69
81
  },
70
82
  backFace() {
71
83
  return {
72
- img:
73
- this.options.back.img && this.options.back.img.asset
74
- ? this.options.back.img.asset.public_url
75
- : '',
76
- altText: this.options.back.imgAltText
77
- ? this.options.back.imgAltText
84
+ imageAsset: this.options.back.imageAsset,
85
+ imageAlt: this.options.back.imageAlt
86
+ ? this.options.back.imageAlt
78
87
  : '',
79
88
  text: this.options.back.text,
80
89
  header: this.options.back.header,
@@ -1,8 +1,8 @@
1
1
  <template>
2
2
  <div>
3
- <h3 v-if="block.metadata.config.title">
3
+ <h2 v-if="block.metadata.config.title">
4
4
  {{ block.metadata.config.title }}
5
- </h3>
5
+ </h2>
6
6
 
7
7
  <p v-if="block.metadata.config.instructions">
8
8
  {{ block.metadata.config.instructions }}
@@ -13,6 +13,7 @@
13
13
  <v-btn
14
14
  variant="elevated"
15
15
  color="primary"
16
+ elevation="0"
16
17
  outlined
17
18
  fab
18
19
  small
@@ -25,6 +26,7 @@
25
26
  <v-btn
26
27
  variant="elevated"
27
28
  color="primary"
29
+ elevation="0"
28
30
  outlined
29
31
  fab
30
32
  small
@@ -38,12 +40,12 @@
38
40
  :key="index"
39
41
  >
40
42
  <v-sheet height="100%" tile>
41
- <flashcard
43
+ <Flashcard
44
+ v-model="block.metadata.config.cards[index].side"
42
45
  :options="card"
43
46
  :slide="block.metadata.config.currentSlide"
44
- v-model="block.metadata.config.cards[index].side"
45
- @click=""
46
47
  :key="seed + '-' + block.metadata.config.currentSlide"
48
+ :assets="block.assets"
47
49
  />
48
50
  </v-sheet>
49
51
  </v-carousel-item>
@@ -84,6 +86,9 @@ export default {
84
86
  )
85
87
  this.block.metadata.config.instructions = ''
86
88
  }
89
+ if (_.isEmpty(this.block.assets)) {
90
+ this.block.assets = []
91
+ }
87
92
 
88
93
  if (_.isEmpty(this.block.metadata.config.cards)) {
89
94
  this.block.metadata.config.cards = []