@windward/core 0.7.0 → 0.8.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/Blocks/Accordion.vue +10 -2
  2. package/components/Content/Blocks/BlockQuote.vue +6 -2
  3. package/components/Content/Blocks/ClickableIcons.vue +10 -2
  4. package/components/Content/Blocks/Email.vue +7 -7
  5. package/components/Content/Blocks/HorizontalRule.vue +2 -0
  6. package/components/Content/Blocks/OpenResponse.vue +25 -0
  7. package/components/Content/Blocks/OpenResponseCollate.vue +13 -12
  8. package/components/Content/Blocks/ScenarioChoice.vue +10 -2
  9. package/components/Content/Blocks/Tab.vue +17 -3
  10. package/components/Content/Blocks/UserUpload.vue +5 -3
  11. package/components/Content/Blocks/Video.vue +33 -7
  12. package/components/Settings/AccordionSettings.vue +20 -34
  13. package/components/Settings/BlockQuoteSettings.vue +17 -41
  14. package/components/Settings/ClickableIconsSettings.vue +18 -40
  15. package/components/Settings/EmailSettings.vue +12 -38
  16. package/components/Settings/FileDownloadSettings.vue +10 -35
  17. package/components/Settings/ImageSettings.vue +3 -9
  18. package/components/Settings/OpenResponseCollateSettings.vue +47 -55
  19. package/components/Settings/OpenResponseSettings.vue +62 -36
  20. package/components/Settings/ScenarioChoiceSettings.vue +13 -35
  21. package/components/Settings/TabSettings.vue +8 -33
  22. package/components/Settings/UserUploadSettings.vue +6 -30
  23. package/components/Settings/VideoSettings/SourcePicker.vue +1 -0
  24. package/components/Settings/VideoSettings.vue +6 -42
  25. package/components/utils/TinyMCEWrapper.vue +6 -3
  26. package/helpers/GlossaryHelper.ts +12 -2
  27. package/i18n/en-US/components/settings/open_response_collate.ts +1 -1
  28. package/i18n/en-US/components/settings/scenario_choice.ts +3 -2
  29. package/i18n/en-US/components/settings/video.ts +1 -1
  30. package/i18n/en-US/shared/settings.ts +1 -1
  31. package/i18n/es-ES/components/settings/open_response_collate.ts +1 -1
  32. package/i18n/es-ES/components/settings/scenario_choice.ts +3 -2
  33. package/i18n/es-ES/components/settings/video.ts +1 -1
  34. package/i18n/es-ES/shared/settings.ts +1 -1
  35. package/i18n/sv-SE/components/settings/open_response_collate.ts +1 -1
  36. package/i18n/sv-SE/components/settings/scenario_choice.ts +3 -2
  37. package/i18n/sv-SE/components/settings/video.ts +1 -1
  38. package/package.json +2 -2
  39. package/test/__mocks__/modelMock.js +1 -1
  40. package/test/helpers/GlossaryHelper.spec.js +22 -3
  41. package/test/mocks.js +8 -0
@@ -6,17 +6,17 @@
6
6
  :autofocus="true"
7
7
  ref="title"
8
8
  outlined
9
- :counter="50"
10
- :rules="validation.shortInputRules"
9
+ :rules="$Validation.getRule('block.title')"
10
+ :counter="$Validation.getLimit('block.title')"
11
11
  :label="$t('components.content.settings.base.title')"
12
12
  :disabled="render"
13
13
  ></v-text-field>
14
14
  <v-textarea
15
15
  v-model="block.metadata.config.instructions"
16
16
  outlined
17
- :rules="validation.instructionRule"
17
+ :rules="$Validation.getRule('block.instructions')"
18
+ :counter="$Validation.getLimit('block.instructions')"
18
19
  auto-grow
19
- :counter="255"
20
20
  :label="$t('components.content.settings.base.instructions')"
21
21
  :disabled="render"
22
22
  ></v-textarea>
@@ -42,8 +42,8 @@
42
42
  <v-container :key="expansionPanelKey">
43
43
  <v-text-field
44
44
  v-model="block.metadata.config.emails[index].from"
45
- :rules="validation.shortInputRules"
46
- :counter="50"
45
+ :rules="$Validation.getRule('shortInput')"
46
+ :counter="$Validation.getLimit('shortInput')"
47
47
  outlined
48
48
  :label="
49
49
  $t(
@@ -54,8 +54,8 @@
54
54
  ></v-text-field>
55
55
  <v-text-field
56
56
  v-model="block.metadata.config.emails[index].to"
57
- :rules="validation.shortInputRules"
58
- :counter="50"
57
+ :rules="$Validation.getRule('shortInput')"
58
+ :counter="$Validation.getLimit('shortInput')"
59
59
  outlined
60
60
  :label="
61
61
  $t('windward.core.components.settings.email.to')
@@ -64,8 +64,8 @@
64
64
  ></v-text-field>
65
65
  <v-text-field
66
66
  v-model="block.metadata.config.emails[index].cc"
67
- :rules="validation.shortInputRules"
68
- :counter="50"
67
+ :rules="$Validation.getRule('shortInput')"
68
+ :counter="$Validation.getLimit('shortInput')"
69
69
  outlined
70
70
  :label="
71
71
  $t('windward.core.components.settings.email.cc')
@@ -76,8 +76,8 @@
76
76
  v-model="
77
77
  block.metadata.config.emails[index].subject
78
78
  "
79
- :rules="validation.shortInputRules"
80
- :counter="50"
79
+ :rules="$Validation.getRule('shortInput')"
80
+ :counter="$Validation.getLimit('shortInput')"
81
81
  outlined
82
82
  :label="
83
83
  $t(
@@ -213,32 +213,6 @@ export default {
213
213
  loading: false,
214
214
  expansionPanelKey: 0,
215
215
  editingPanel: 0,
216
- validation: {
217
- shortInputRules: [
218
- (v) => {
219
- if (v && v.length >= 50) {
220
- return this.$t(
221
- 'windward.core.shared.settings.errors.input_limitations',
222
- [50]
223
- )
224
- } else {
225
- return true
226
- }
227
- },
228
- ],
229
- instructionRule: [
230
- (v) => {
231
- if (v && v.length >= 255) {
232
- return this.$t(
233
- 'windward.core.shared.settings.errors.input_limitations',
234
- [255]
235
- )
236
- } else {
237
- return true
238
- }
239
- },
240
- ],
241
- },
242
216
  }
243
217
  },
244
218
  beforeDestroy() {
@@ -1,19 +1,21 @@
1
1
  <template>
2
2
  <div>
3
3
  <v-text-field
4
+ id="block-settings-title"
4
5
  v-model="block.metadata.config.title"
5
6
  outlined
6
- :counter="50"
7
- :rules="validation.shortInputRules"
7
+ :rules="$Validation.getRule('block.title')"
8
+ :counter="$Validation.getLimit('block.title')"
8
9
  :autofocus="true"
9
10
  :label="$t('components.content.settings.base.title')"
10
11
  :disabled="render"
11
12
  ></v-text-field>
12
13
  <v-textarea
14
+ id="block-settings-instructions"
13
15
  v-model="block.metadata.config.instructions"
14
16
  outlined
15
- :counter="255"
16
- :rules="validation.instructionRule"
17
+ :rules="$Validation.getRule('block.instructions')"
18
+ :counter="$Validation.getLimit('block.instructions')"
17
19
  :disabled="render"
18
20
  :label="$t('components.content.settings.base.instructions')"
19
21
  ></v-textarea>
@@ -39,8 +41,8 @@
39
41
  <v-text-field
40
42
  v-model="block.metadata.config.items[index].name"
41
43
  :autofocus="true"
42
- :counter="50"
43
- :rules="validation.shortInputRules"
44
+ :rules="$Validation.getRule('shortInput')"
45
+ :counter="$Validation.getLimit('shortInput')"
44
46
  outlined
45
47
  :label="
46
48
  $t(
@@ -79,7 +81,7 @@
79
81
  ><v-icon>mdi-plus</v-icon
80
82
  >{{
81
83
  $t(
82
- 'windward.core.components.settings.file_download.add'
84
+ 'windward.core.components.settings.file_download.place_file'
83
85
  )
84
86
  }}</v-btn
85
87
  >
@@ -98,34 +100,7 @@ export default {
98
100
  extends: BaseContentSettings,
99
101
  components: { TextEditor, SortableExpansionPanel },
100
102
  data() {
101
- return {
102
- validation: {
103
- shortInputRules: [
104
- (v) => {
105
- if (v && v.length >= 50) {
106
- return this.$t(
107
- 'windward.core.shared.settings.errors.input_limitations',
108
- [50]
109
- )
110
- } else {
111
- return true
112
- }
113
- },
114
- ],
115
- instructionRule: [
116
- (v) => {
117
- if (v && v.length >= 255) {
118
- return this.$t(
119
- 'windward.core.shared.settings.errors.input_limitations',
120
- [255]
121
- )
122
- } else {
123
- return true
124
- }
125
- },
126
- ],
127
- },
128
- }
103
+ return {}
129
104
  },
130
105
  computed: {
131
106
  filename() {
@@ -104,7 +104,7 @@
104
104
  outlined
105
105
  counter
106
106
  maxlength="125"
107
- :rules="validation.textRules"
107
+ :rules="$Validation.getRule('exists')"
108
108
  disabled
109
109
  >
110
110
  </v-text-field>
@@ -118,7 +118,7 @@
118
118
  :label="
119
119
  $t('windward.core.components.navigation.image.default_alt')
120
120
  "
121
- :rules="validation.textRules"
121
+ :rules="$Validation.getRule('exists')"
122
122
  :disabled="render"
123
123
  >
124
124
  <template #append>
@@ -245,13 +245,7 @@ export default {
245
245
  }
246
246
  },
247
247
  data() {
248
- return {
249
- validation: {
250
- textRules: [
251
- (v) => !!v || this.$t('shared.forms.errors.required'),
252
- ],
253
- },
254
- }
248
+ return {}
255
249
  },
256
250
  watch: {},
257
251
  mounted() {},
@@ -33,41 +33,31 @@
33
33
  color="primary"
34
34
  @change="onLinkedChange"
35
35
  >
36
- <draggable
37
- v-bind="dragOptions"
38
- :list="contentBlocks"
39
- @change="onDragChange"
36
+ <v-list-item
37
+ v-for="contentBlock in contentBlocks"
38
+ :key="contentBlock.block_id"
39
+ :value="contentBlock.block_id"
40
40
  >
41
- <v-list-item
42
- v-for="contentBlock in contentBlocks"
43
- :key="contentBlock.block_id"
44
- :value="contentBlock.block_id"
45
- >
46
- <template #default="{ active }">
47
- <v-list-item-icon>
48
- <v-icon>mdi-drag</v-icon>
49
- </v-list-item-icon>
50
-
51
- <v-list-item-content>
52
- <v-list-item-title>
53
- {{
54
- contentBlock.block.body.replace(
55
- /<[^>]*>?/gm,
56
- ''
57
- )
58
- }}
59
- </v-list-item-title>
60
- </v-list-item-content>
61
- <v-list-item-action>
62
- <v-checkbox
63
- :input-value="active"
64
- color="primary"
65
- :disabled="render"
66
- ></v-checkbox>
67
- </v-list-item-action>
68
- </template>
69
- </v-list-item>
70
- </draggable>
41
+ <template #default="{ active }">
42
+ <v-list-item-content>
43
+ <v-list-item-title>
44
+ {{
45
+ contentBlock.body.replace(
46
+ /<[^>]*>?/gm,
47
+ ''
48
+ )
49
+ }}
50
+ </v-list-item-title>
51
+ </v-list-item-content>
52
+ <v-list-item-action>
53
+ <v-checkbox
54
+ :input-value="active"
55
+ color="primary"
56
+ :disabled="render"
57
+ ></v-checkbox>
58
+ </v-list-item-action>
59
+ </template>
60
+ </v-list-item>
71
61
  </v-list-item-group>
72
62
  </v-list>
73
63
  </v-form>
@@ -84,7 +74,7 @@ import ContentBlock from '~/models/ContentBlock'
84
74
  import Course from '~/models/Course'
85
75
 
86
76
  export default {
87
- name: 'ImageSettings',
77
+ name: 'OpenResponseCollateSettings',
88
78
  extends: BaseContentSettings,
89
79
  components: { draggable, TextEditor },
90
80
  props: {
@@ -117,6 +107,8 @@ export default {
117
107
  )
118
108
  .for(new Course({ id: this.course.id }))
119
109
  .get()
110
+
111
+ this.sortContentBlocks(this.contentBlocks)
120
112
  },
121
113
  beforeMount() {
122
114
  if (_.isEmpty(this.block)) {
@@ -141,34 +133,34 @@ export default {
141
133
  if (!_.isBoolean(this.block.metadata.config.include_prompts)) {
142
134
  this.block.metadata.config.include_prompts = false
143
135
  }
144
-
145
136
  this.linked = this.block.metadata.config.linked
146
137
  },
147
138
  watch: {},
148
139
  mounted() {},
149
140
  methods: {
150
- // Called when the order changes
151
- onDragChange(e) {
152
- this.setLinkedBlocks()
141
+ sortContentBlocks(contentBlocks) {
142
+ let contentBlocksByPage = []
143
+ const blockMap = []
144
+ // getting page order
145
+ const contentBlockTree = this.$ContentService.getFlatTree()
146
+ contentBlockTree.forEach(function (page, index) {
147
+ contentBlocks.forEach((block) => {
148
+ // If the block is on this page and it wasn't already used on a different page
149
+ if (
150
+ page.content_id === block.content_id &&
151
+ !blockMap.includes(block.block_id)
152
+ ) {
153
+ contentBlocksByPage.push(block)
154
+ blockMap.push(block.block_id)
155
+ }
156
+ })
157
+ })
158
+ this.contentBlocks = contentBlocksByPage
153
159
  },
154
160
  // Called when blocks are added / removed
155
161
  onLinkedChange() {
156
- this.setLinkedBlocks()
157
- },
158
- setLinkedBlocks() {
159
- const linkedBlockIds = []
160
-
161
- // Loop over content blocks since they have the correct order we want to collate
162
- this.contentBlocks.forEach((contentBlock) => {
163
- // If the unsorted this.linked includes the block id, add it in the right order
164
- if (this.linked.includes(contentBlock.block_id)) {
165
- linkedBlockIds.push(contentBlock.block_id)
166
- }
167
- })
168
-
169
- // Set the linked and also body for convenience
170
- this.block.metadata.config.linked = linkedBlockIds
171
- this.block.body = linkedBlockIds.join()
162
+ // update block with linked open response for download
163
+ this.block.metadata.config.linked = this.linked
172
164
  },
173
165
  },
174
166
  }
@@ -1,43 +1,63 @@
1
1
  <template>
2
2
  <v-container>
3
- <v-form>
4
- <p>
5
- {{
6
- $t(
7
- 'windward.core.components.settings.open_response.question'
8
- )
9
- }}
10
- </p>
11
- <TextEditor
12
- v-model="block.body"
13
- :height="200"
3
+ <v-row class="pl-3 pr-3">
4
+ <v-text-field
5
+ id="block-settings-title"
6
+ v-model="block.metadata.config.title"
7
+ :autofocus="true"
8
+ :rules="$Validation.getRule('block.title')"
9
+ :counter="$Validation.getLimit('block.title')"
10
+ outlined
11
+ :label="
12
+ $t('windward.core.components.settings.clickable_icon.title')
13
+ "
14
14
  :disabled="render"
15
- ></TextEditor>
16
- <p class="pt-4">
17
- {{
18
- $t(
19
- 'windward.core.components.settings.open_response.sample_response'
20
- )
21
- }}
22
- </p>
23
- <TextEditor
24
- v-model="block.metadata.config.sample_response"
25
- :height="200"
15
+ ></v-text-field>
16
+ <v-textarea
17
+ id="block-settings-instructions"
18
+ v-model="block.metadata.config.instructions"
19
+ :rules="$Validation.getRule('block.instructions')"
20
+ :counter="$Validation.getLimit('block.instructions')"
21
+ outlined
22
+ :label="$t('components.content.settings.base.instructions')"
26
23
  :disabled="render"
27
- ></TextEditor>
28
- <p class="pt-4">
29
- {{
30
- $t(
31
- 'windward.core.components.settings.open_response.starting_text'
32
- )
33
- }}
34
- </p>
35
- <TextEditor
36
- v-model="block.metadata.config.starting_text"
37
- :height="200"
38
- :disabled="render"
39
- ></TextEditor>
40
- </v-form>
24
+ ></v-textarea>
25
+ </v-row>
26
+ <p>
27
+ {{ $t('windward.core.components.settings.open_response.question') }}
28
+ </p>
29
+ <TextEditor
30
+ id="block-settings-body"
31
+ v-model="block.body"
32
+ :height="200"
33
+ :disabled="render"
34
+ ></TextEditor>
35
+ <p class="pt-4">
36
+ {{
37
+ $t(
38
+ 'windward.core.components.settings.open_response.sample_response'
39
+ )
40
+ }}
41
+ </p>
42
+ <TextEditor
43
+ id="block-settings-sample-response"
44
+ v-model="block.metadata.config.sample_response"
45
+ :height="200"
46
+ :disabled="render"
47
+ ></TextEditor>
48
+ <p class="pt-4">
49
+ {{
50
+ $t(
51
+ 'windward.core.components.settings.open_response.starting_text'
52
+ )
53
+ }}
54
+ </p>
55
+ <TextEditor
56
+ id="block-settings-starting-text"
57
+ v-model="block.metadata.config.starting_text"
58
+ :height="200"
59
+ :disabled="render"
60
+ ></TextEditor>
41
61
  </v-container>
42
62
  </template>
43
63
 
@@ -67,6 +87,12 @@ export default {
67
87
  if (_.isEmpty(this.block.metadata.config)) {
68
88
  this.block.metadata.config = {}
69
89
  }
90
+ if (_.isEmpty(this.block.metadata.config.title)) {
91
+ this.block.metadata.config.title = ''
92
+ }
93
+ if (_.isEmpty(this.block.metadata.config.instructions)) {
94
+ this.block.metadata.config.instructions = ''
95
+ }
70
96
  if (_.isEmpty(this.block.metadata.config.sample_response)) {
71
97
  this.block.metadata.config.sample_response = ''
72
98
  }
@@ -3,11 +3,11 @@
3
3
  <v-container class="pa-0">
4
4
  <v-col class="pa-0">
5
5
  <v-text-field
6
+ id="block-settings-title"
6
7
  v-model="block.metadata.config.title"
7
- :rules="validation.shortInputRules"
8
- :counter="50"
8
+ :rules="$Validation.getRule('block.title')"
9
+ :counter="$Validation.getLimit('block.title')"
9
10
  outlined
10
- id="title"
11
11
  :label="
12
12
  $t(
13
13
  'windward.core.components.settings.scenario_choice.title'
@@ -16,10 +16,10 @@
16
16
  :disabled="render"
17
17
  ></v-text-field>
18
18
  <v-textarea
19
+ id="block-settings-instructions"
19
20
  v-model="block.metadata.config.description"
20
- id="description"
21
- :rules="validation.instructionRule"
22
- :counter="255"
21
+ :rules="$Validation.getRule('block.instructions')"
22
+ :counter="$Validation.getLimit('block.instructions')"
23
23
  outlined
24
24
  :label="$t('components.content.settings.base.instructions')"
25
25
  :disabled="render"
@@ -77,8 +77,8 @@
77
77
  v-model="
78
78
  block.metadata.config.items[index].title
79
79
  "
80
- :rules="validation.shortInputRules"
81
- :counter="50"
80
+ :rules="$Validation.getRule('longInput')"
81
+ :counter="$Validation.getLimit('longInput')"
82
82
  outlined
83
83
  :id="'item-' + index + '-title'"
84
84
  :label="
@@ -128,7 +128,11 @@
128
128
  >
129
129
  <v-icon>mdi-plus</v-icon>
130
130
  <span v-if="block.metadata.config.items.length <= 26">
131
- {{ $t('shared.forms.add') }}
131
+ {{
132
+ $t(
133
+ 'windward.core.components.settings.scenario_choice.add_choice'
134
+ )
135
+ }}
132
136
  </span>
133
137
  <span v-else>
134
138
  {{
@@ -249,32 +253,6 @@ export default {
249
253
  value: 'number',
250
254
  },
251
255
  ],
252
- validation: {
253
- shortInputRules: [
254
- (v) => {
255
- if (v && v.length >= 50) {
256
- return this.$t(
257
- 'windward.core.shared.settings.errors.input_limitations',
258
- [50]
259
- )
260
- } else {
261
- return true
262
- }
263
- },
264
- ],
265
- instructionRule: [
266
- (v) => {
267
- if (v && v.length >= 255) {
268
- return this.$t(
269
- 'windward.core.shared.settings.errors.input_limitations',
270
- [255]
271
- )
272
- } else {
273
- return true
274
- }
275
- },
276
- ],
277
- },
278
256
  }
279
257
  },
280
258
  beforeMount() {
@@ -2,21 +2,22 @@
2
2
  <div>
3
3
  <v-row class="pl-3 pr-3">
4
4
  <v-text-field
5
+ id="block-settings-title"
5
6
  v-model="block.metadata.config.title"
6
7
  :autofocus="true"
7
- :rules="validation.shortInputRules"
8
- :counter="50"
8
+ :rules="$Validation.getRule('block.title')"
9
+ :counter="$Validation.getLimit('block.title')"
9
10
  outlined
10
- id="title"
11
11
  :label="
12
12
  $t('windward.core.components.settings.clickable_icon.title')
13
13
  "
14
14
  :disabled="render"
15
15
  ></v-text-field>
16
16
  <v-textarea
17
+ id="block-settings-instructions"
17
18
  v-model="block.metadata.config.instructions"
18
- :rules="validation.instructionRule"
19
- :counter="255"
19
+ :rules="$Validation.getRule('block.instructions')"
20
+ :counter="$Validation.getLimit('block.instructions')"
20
21
  outlined
21
22
  :label="$t('components.content.settings.base.instructions')"
22
23
  :disabled="render"
@@ -43,8 +44,8 @@
43
44
  outlined
44
45
  :autofocus="true"
45
46
  v-model="block.metadata.config.items[index].tabHeader"
46
- :counter="50"
47
- :rules="validation.shortInputRules"
47
+ :rules="$Validation.getRule('shortInput')"
48
+ :counter="$Validation.getLimit('shortInput')"
48
49
  :label="'item ' + (index + 1)"
49
50
  :disabled="render"
50
51
  ></v-text-field>
@@ -156,32 +157,6 @@ export default {
156
157
  textEditorUpdateKey: Crypto.id(),
157
158
  valid: true,
158
159
  loading: false,
159
- validation: {
160
- shortInputRules: [
161
- (v) => {
162
- if (v && v.length >= 50) {
163
- return this.$t(
164
- 'windward.core.shared.settings.errors.input_limitations',
165
- [50]
166
- )
167
- } else {
168
- return true
169
- }
170
- },
171
- ],
172
- instructionRule: [
173
- (v) => {
174
- if (v && v.length >= 255) {
175
- return this.$t(
176
- 'windward.core.shared.settings.errors.input_limitations',
177
- [255]
178
- )
179
- } else {
180
- return true
181
- }
182
- },
183
- ],
184
- },
185
160
  }
186
161
  },
187
162
  mounted() {