@windward/games 0.0.3 → 0.0.4

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.
@@ -0,0 +1,274 @@
1
+ <template>
2
+ <div>
3
+ <v-form ref="form" v-model="valid" v-if="!loading">
4
+ <v-text-field
5
+ v-model="block.metadata.config.title"
6
+ :counter="50"
7
+ :label="
8
+ $t(
9
+ 'plugin.games.components.settings.bucket_game.form.title'
10
+ )
11
+ "
12
+ ref="title"
13
+ ></v-text-field>
14
+ <br />
15
+ <v-textarea
16
+ outlined
17
+ auto-grow
18
+ v-model="block.metadata.config.instructions"
19
+ :counter="255"
20
+ :label="
21
+ $t(
22
+ 'plugin.games.components.settings.bucket_game.form.instructions'
23
+ )
24
+ "
25
+ ></v-textarea>
26
+ <v-expansion-panels flat>
27
+ <v-expansion-panel>
28
+ <v-expansion-panel-header class="pa-0"
29
+ ><h3>
30
+ {{
31
+ $t(
32
+ 'plugin.games.components.settings.crossword.crossword_items'
33
+ )
34
+ }}
35
+ </h3></v-expansion-panel-header
36
+ >
37
+ <v-expansion-panel-content class="ma-0">
38
+ <v-container class="pa-0">
39
+ <p>
40
+ {{
41
+ $t(
42
+ 'plugin.games.components.settings.crossword.min_length'
43
+ )
44
+ }}
45
+ </p>
46
+ <v-card
47
+ v-for="(item, index) in block.metadata.config
48
+ .words"
49
+ :key="'bucket_' + index"
50
+ class="pa-2 flex-fill cardOutline"
51
+ elevation="0"
52
+ outlined
53
+ tile
54
+ >
55
+ <v-row class="itemHeight">
56
+ <p
57
+ class="text-truncate pa-0 ma-0 seventy"
58
+ @click="onOpenEditor(index)"
59
+ v-on:keyup.enter="onOpenEditor(index)"
60
+ @mouseover="onHover"
61
+ @mouseleave="onHoverLeave"
62
+ :class="cursor"
63
+ tabindex="0"
64
+ >
65
+ <v-icon class="pl-2"
66
+ >mdi-gesture-tap-hold</v-icon
67
+ >
68
+ {{
69
+ item.word
70
+ ? item.word
71
+ : $t(
72
+ 'plugin.games.components.settings.bucket_game.form.enter_text'
73
+ )
74
+ }}
75
+ </p>
76
+ <v-icon
77
+ class="twenty"
78
+ @click="onDelete(index)"
79
+ >mdi-delete-outline</v-icon
80
+ >
81
+ </v-row>
82
+ <v-textarea
83
+ v-if="item.expand"
84
+ outlined
85
+ :autofocus="true"
86
+ :label="
87
+ $t(
88
+ 'plugin.games.components.settings.crossword.word'
89
+ )
90
+ "
91
+ class="pt-4"
92
+ v-model="
93
+ block.metadata.config.words[index].word
94
+ "
95
+ ></v-textarea>
96
+ <v-textarea
97
+ v-if="item.expand"
98
+ outlined
99
+ :label="
100
+ $t(
101
+ 'plugin.games.components.settings.crossword.description'
102
+ )
103
+ "
104
+ class="pt-4"
105
+ v-model="
106
+ block.metadata.config.words[index]
107
+ .description
108
+ "
109
+ ></v-textarea>
110
+ </v-card>
111
+ <p
112
+ @mouseover="onHover"
113
+ @mouseleave="onHoverLeave"
114
+ @click="onAddElement"
115
+ v-on:keyup.enter="onAddElement"
116
+ class="fullWidth"
117
+ :class="cursor"
118
+ tabindex="0"
119
+ >
120
+ <v-icon class="primary addIcon"
121
+ >mdi-plus</v-icon
122
+ >
123
+ {{
124
+ $t(
125
+ 'plugin.games.components.content.blocks.crossword.add_element'
126
+ )
127
+ }}
128
+ </p>
129
+ </v-container>
130
+ </v-expansion-panel-content>
131
+ </v-expansion-panel>
132
+ </v-expansion-panels>
133
+ </v-form>
134
+ <div v-if="loading" class="text-center">
135
+ <v-progress-circular
136
+ :size="70"
137
+ :width="7"
138
+ color="primary"
139
+ indeterminate
140
+ ></v-progress-circular>
141
+ </div>
142
+ </div>
143
+ </template>
144
+
145
+ <script>
146
+ import _ from 'lodash'
147
+ import BaseContentSettings from '~/components/Content/Tool/BaseContentSettings.js'
148
+ export default {
149
+ name: 'CrosswordPuzzleSettingsManager',
150
+ extends: BaseContentSettings,
151
+ components: {},
152
+ beforeMount() {
153
+ if (_.isEmpty(this.block)) {
154
+ this.block = {}
155
+ }
156
+ if (_.isEmpty(this.block.metadata)) {
157
+ this.block.metadata = {}
158
+ }
159
+ if (_.isEmpty(this.block.metadata.config)) {
160
+ this.block.metadata.config = {}
161
+ }
162
+ if (_.isEmpty(this.block.metadata.config.title)) {
163
+ this.block.metadata.config.title = ''
164
+ }
165
+ if (_.isEmpty(this.block.metadata.config.instructions)) {
166
+ this.block.metadata.config.instructions = ''
167
+ }
168
+ if (_.isEmpty(this.block.metadata.config.words)) {
169
+ this.block.metadata.config.words = []
170
+ let counter = 0
171
+ while (counter < 2) {
172
+ const default_object = {
173
+ id: counter,
174
+ word: '',
175
+ description: '',
176
+ expand: false,
177
+ }
178
+ counter = counter + 1
179
+ !this.block.metadata.config.words.push(default_object)
180
+ }
181
+ }
182
+ },
183
+ data() {
184
+ return {
185
+ valid: true,
186
+ loading: false,
187
+ cursor: null,
188
+ }
189
+ },
190
+ methods: {
191
+ onAddElement() {
192
+ this.block.metadata.config.words.forEach((element) => {
193
+ element.expand = false
194
+ })
195
+ const default_object = {
196
+ id: this.block.metadata.config.words.length,
197
+ word: '',
198
+ description: '',
199
+ expand: true,
200
+ }
201
+ this.block.metadata.config.words.push(default_object)
202
+ },
203
+ onDelete(index) {
204
+ this.block.metadata.config.words.splice(index, 1)
205
+ let counter = 0
206
+ this.block.metadata.config.words.forEach((element) => {
207
+ element.id = counter
208
+ counter = counter + 1
209
+ })
210
+ if (this.block.metadata.config.words.length < 2) {
211
+ this.onAddElement()
212
+ }
213
+ },
214
+ onOpenEditor(index) {
215
+ this.block.metadata.config.words[index].expand =
216
+ !this.block.metadata.config.words[index].expand
217
+ this.block.metadata.config.words.forEach((element) => {
218
+ if (index !== element.id) {
219
+ element.expand = false
220
+ }
221
+ })
222
+ },
223
+ onHover(index) {
224
+ this.cursor = 'changePointer'
225
+ },
226
+ onHoverLeave() {
227
+ this.cursor = ''
228
+ },
229
+ },
230
+ }
231
+ </script>
232
+ <style lang="scss" scoped>
233
+ .v-progress-circular {
234
+ margin: 1rem;
235
+ }
236
+ .changePointer {
237
+ cursor: pointer !important;
238
+ }
239
+ .cardOutline {
240
+ border: 2px solid var(--v-primary-base);
241
+ margin-bottom: 8px;
242
+ }
243
+ .fullWidth {
244
+ display: flex;
245
+ justify-content: center;
246
+ align-items: center;
247
+ font-weight: bold;
248
+ font-size: 16px;
249
+ }
250
+ .itemHeight {
251
+ display: flex;
252
+ align-content: center;
253
+ justify-content: space-between;
254
+ height: 60px;
255
+ }
256
+ .seventy {
257
+ width: 70%;
258
+ height: 100%;
259
+ display: flex;
260
+ align-items: center;
261
+ }
262
+ .twenty {
263
+ width: 20%;
264
+ height: 90%;
265
+ margin-top: 3px;
266
+ border-left: 2px solid var(--v-primary-base);
267
+ }
268
+ .addIcon {
269
+ margin-right: 5px;
270
+ }
271
+ .v-expansion-panel-content::v-deep .v-expansion-panel-content__wrap {
272
+ padding: 0 !important;
273
+ }
274
+ </style>
@@ -209,11 +209,14 @@ export default {
209
209
  },
210
210
  methods: {
211
211
  onAddWord() {
212
+ this.block.metadata.config.words.forEach((element) => {
213
+ element.expand = false
214
+ })
212
215
  let defaultWord = {
213
216
  id: this.block.metadata.config.words.length + 1,
214
217
  value: '',
215
218
  hint: '',
216
- expand: false,
219
+ expand: true,
217
220
  }
218
221
  this.block.metadata.config.words.push(defaultWord)
219
222
  },
@@ -0,0 +1,7 @@
1
+ export default {
2
+ crossword: 'Crossword Game',
3
+ add_element: 'Add Element',
4
+ placeholder:
5
+ 'THIS IS EXAMPLE DATA! MUST ENTER MORE THAN TWO WORDS & DESCRIPTIONS TO SEE EDITED TEXT',
6
+ play_again: 'Play Again',
7
+ }
@@ -6,6 +6,7 @@ import quizshow_game from './quizshow_game'
6
6
  import slideshow from './slideshow'
7
7
  import multiple_choice from './multiple_choice'
8
8
  import word_jumble from './word_jumble'
9
+ import crossword from './crossword'
9
10
 
10
11
  export default {
11
12
  bucket_game,
@@ -16,4 +17,5 @@ export default {
16
17
  slideshow,
17
18
  multiple_choice,
18
19
  word_jumble,
20
+ crossword,
19
21
  }
@@ -0,0 +1,6 @@
1
+ export default {
2
+ crossword_items: 'Crossword Items',
3
+ word: 'Word',
4
+ description: 'Description',
5
+ min_length: 'Cannot have less than two words',
6
+ }
@@ -6,6 +6,7 @@ import slideshow from './slideshow'
6
6
  import multiple_choice from './multiple_choice'
7
7
  import sorting_game from './sorting_game'
8
8
  import word_jumble from './word_jumble'
9
+ import crossword from './crossword'
9
10
 
10
11
  export default {
11
12
  bucket_game,
@@ -16,4 +17,5 @@ export default {
16
17
  slideshow,
17
18
  multiple_choice,
18
19
  sorting_game,
20
+ crossword,
19
21
  }
@@ -4,7 +4,7 @@ export default {
4
4
  instructions: 'Instructions',
5
5
  click: 'Click to enter text',
6
6
  label: 'Word for jumbling',
7
- hint: 'Hint for word',
7
+ hint: 'Clue for word',
8
8
  add: 'Add Word',
9
9
  feedback_correct: 'Feedback when correct',
10
10
  feedback_incorrect: 'Feedback when incorrect',
@@ -8,6 +8,7 @@ export default {
8
8
  slideshow: 'Slideshow',
9
9
  multiple_choice: 'Multiple Choice',
10
10
  word_jumble: 'Word Jumble',
11
+ crossword_puzzle: 'Crossword',
11
12
  },
12
13
  grouping: {
13
14
  game: 'Activities',
@@ -8,5 +8,6 @@ export default {
8
8
  quizshow_manager: 'Quizshow Manager',
9
9
  multiple_choice_manager: 'Multiple Choice Manager',
10
10
  wordjumble_manager: 'Word Jumble Manager',
11
+ crossword_puzzle_manager: 'Crossword Puzzle Manager',
11
12
  },
12
13
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@windward/games",
3
- "version": "0.0.3",
3
+ "version": "0.0.4",
4
4
  "description": "Windward UI Plugin Games",
5
5
  "main": "plugin.js",
6
6
  "scripts": {
package/plugin.js CHANGED
@@ -15,6 +15,8 @@ import quizShow from './components/content/blocks/quizshowGame/QuizShow'
15
15
  import QuizShowSettingsManager from './components/settings/QuizShowSettingsManager'
16
16
  import MultipleChoice from './components/content/blocks/multipleChoice/MultipleChoice.vue'
17
17
  import MultipleChoiceSettingsManager from './components/settings/MultipleChoiceSettingsManager'
18
+ import CrosswordPuzzle from './components/content/blocks/crosswordPuzzle/CrosswordPuzzle.vue'
19
+ import CrosswordPuzzleSettingsManager from './components/settings/CrosswordPuzzleSettingsManager.vue'
18
20
 
19
21
  export default {
20
22
  name: 'Windward Games Plugin',
@@ -107,12 +109,22 @@ export default {
107
109
  tag: 'games-wordjumble-game',
108
110
  template: WordJumble,
109
111
  metadata: {
110
- icon: 'mdi-alpha-w-box-outline',
112
+ icon: 'mdi-ab-testing',
111
113
  name: 'plugin.games.shared.content_blocks.title.word_jumble',
112
114
  grouping:
113
115
  'plugin.games.shared.content_blocks.grouping.game',
114
116
  },
115
117
  },
118
+ {
119
+ tag: 'games-crossword-puzzle-game',
120
+ template: CrosswordPuzzle,
121
+ metadata: {
122
+ icon: 'mdi-alpha-c-box-outline',
123
+ name: 'plugin.games.shared.content_blocks.title.crossword_puzzle',
124
+ grouping:
125
+ 'plugin.games.shared.content_blocks.grouping.game',
126
+ },
127
+ },
116
128
  ],
117
129
  settings: [
118
130
  {
@@ -187,6 +199,15 @@ export default {
187
199
  name: 'plugin.games.shared.settings.title.wordjumble_manager',
188
200
  },
189
201
  },
202
+ {
203
+ tag: 'games-crossword-puzzle-settings',
204
+ template: CrosswordPuzzleSettingsManager,
205
+ context: ['block.games-crossword-puzzle-game'],
206
+ metadata: {
207
+ icon: 'mdi-cog',
208
+ name: 'plugin.games.shared.settings.title.crossword_puzzle_manager',
209
+ },
210
+ },
190
211
  ],
191
212
  },
192
213
  }
@@ -0,0 +1,49 @@
1
+ import { shallowMount } from '@vue/test-utils'
2
+ import { defaultMocks } from '@windward/core/test/mocks'
3
+ import CrosswordPuzzle from '@/components/content/blocks/crosswordPuzzle/CrosswordPuzzle'
4
+
5
+ import Vuetify from 'vuetify'
6
+ import Vue from 'vue'
7
+ Vue.use(Vuetify)
8
+
9
+ //override default mock
10
+ jest.mock(
11
+ 'lodash',
12
+ () => {
13
+ return {
14
+ cloneDeep: () => {
15
+ return []
16
+ },
17
+ isEmpty: () => {
18
+ return jest.fn()
19
+ },
20
+ flatten: () => {
21
+ return jest.fn()
22
+ },
23
+ get: () => {
24
+ return jest.fn()
25
+ },
26
+ }
27
+ },
28
+ { virtual: true }
29
+ )
30
+ describe('CrosswordPuzzle', () => {
31
+ test('is a Vue instance', () => {
32
+ const wrapper = shallowMount(CrosswordPuzzle, {
33
+ propsData: {
34
+ value: {
35
+ id: '00000000-0000-0000-0000-000000000000',
36
+ name: 'Test Content Page',
37
+ body: '[]',
38
+ metadata: {
39
+ config: {
40
+ words: [],
41
+ },
42
+ },
43
+ },
44
+ },
45
+ mocks: defaultMocks,
46
+ })
47
+ expect(wrapper.vm).toBeTruthy()
48
+ })
49
+ })
@@ -9,7 +9,7 @@ Vue.use(Vuetify)
9
9
  const settings = {}
10
10
  const context = 'block'
11
11
 
12
- describe('Matching game manager', () => {
12
+ describe('Bucket game manager', () => {
13
13
  test('is a Vue instance', () => {
14
14
  const wrapper = shallowMount(BucketGameSettingsManager, {
15
15
  propsData: {
@@ -0,0 +1,103 @@
1
+ import { shallowMount } from '@vue/test-utils'
2
+ import { defaultMocks } from '@windward/core/test/mocks'
3
+ import CrosswordPuzzleSettingsManager from '@/components/settings/CrosswordPuzzleSettingsManager'
4
+
5
+ import Vuetify from 'vuetify'
6
+ import Vue from 'vue'
7
+ Vue.use(Vuetify)
8
+
9
+ const settings = {}
10
+ const context = 'block'
11
+
12
+ describe('Crossword game manager', () => {
13
+ test('is a Vue instance', () => {
14
+ const wrapper = shallowMount(CrosswordPuzzleSettingsManager, {
15
+ propsData: {
16
+ block: {
17
+ id: '00000000-0000-0000-0000-000000000000',
18
+ name: 'Test Content Page',
19
+ body: '{}',
20
+ metadata: { config: {} },
21
+ },
22
+ settings: settings,
23
+ context: context,
24
+ data: {},
25
+ metadata: { config: {} },
26
+ },
27
+ mocks: defaultMocks,
28
+ })
29
+ expect(wrapper.vm).toBeTruthy()
30
+ })
31
+
32
+ test('can add new word', () => {
33
+ const wrapper = shallowMount(CrosswordPuzzleSettingsManager, {
34
+ propsData: {
35
+ block: {
36
+ id: '00000000-0000-0000-0000-000000000000',
37
+ name: 'Test Content Page',
38
+ body: '{}',
39
+ metadata: { config: {} },
40
+ },
41
+ settings: settings,
42
+ context: context,
43
+ data: {},
44
+ metadata: { config: {} },
45
+ },
46
+ mocks: defaultMocks,
47
+ })
48
+ wrapper.vm.onAddElement()
49
+ expect(wrapper.vm.block.metadata.config.words).toEqual([
50
+ {
51
+ id: 0,
52
+ word: '',
53
+ description: '',
54
+ expand: false,
55
+ },
56
+ {
57
+ id: 1,
58
+ word: '',
59
+ description: '',
60
+ expand: false,
61
+ },
62
+ {
63
+ id: 2,
64
+ word: '',
65
+ description: '',
66
+ expand: true,
67
+ },
68
+ ])
69
+ })
70
+
71
+ test('can delete word', () => {
72
+ const wrapper = shallowMount(CrosswordPuzzleSettingsManager, {
73
+ propsData: {
74
+ block: {
75
+ id: '00000000-0000-0000-0000-000000000000',
76
+ name: 'Test Content Page',
77
+ body: '{}',
78
+ metadata: { config: {} },
79
+ },
80
+ settings: settings,
81
+ context: context,
82
+ data: {},
83
+ metadata: { config: {} },
84
+ },
85
+ mocks: defaultMocks,
86
+ })
87
+ wrapper.vm.onDelete(1)
88
+ expect(wrapper.vm.block.metadata.config.words).toEqual([
89
+ {
90
+ id: 0,
91
+ word: '',
92
+ description: '',
93
+ expand: false,
94
+ },
95
+ {
96
+ id: 1,
97
+ word: '',
98
+ description: '',
99
+ expand: true,
100
+ },
101
+ ])
102
+ })
103
+ })
@@ -55,7 +55,7 @@ describe('WordJumble manager', () => {
55
55
  id: 2,
56
56
  value: '',
57
57
  hint: '',
58
- expand: false,
58
+ expand: true,
59
59
  },
60
60
  ])
61
61
  })
@@ -80,7 +80,7 @@ describe('WordJumble manager', () => {
80
80
  id: 1,
81
81
  value: '',
82
82
  hint: '',
83
- expand: false,
83
+ expand: true,
84
84
  },
85
85
  ])
86
86
  })