@windward/core 0.0.5 → 0.0.6

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 (91) hide show
  1. package/README.md +2 -1
  2. package/components/Content/Blocks/ClickableIcons.vue +10 -1
  3. package/components/Content/Blocks/Feedback.vue +12 -4
  4. package/components/Content/Blocks/FeedbackTemplates/FeedbackQuestionOpenResponse.vue +10 -9
  5. package/components/Navigation/Items/AskTheExpert.vue +173 -0
  6. package/components/Settings/ClickableIconsSettings.vue +10 -5
  7. package/components/utils/ContentViewer.vue +15 -4
  8. package/components/utils/FillInBlank/FillInBlankInput.vue +208 -0
  9. package/components/utils/FillInBlank/FillInTheBlanksManager.vue +98 -0
  10. package/components/utils/MathExpressionEditor.vue +8 -6
  11. package/components/utils/TinyMCEWrapper.vue +48 -8
  12. package/components/utils/assets/tinymce/css/content.scss +9 -0
  13. package/components/utils/glossary/CourseGlossary.vue +12 -8
  14. package/components/utils/glossary/CourseGlossaryForm.vue +24 -5
  15. package/helpers/FillInBlankHelper.ts +55 -0
  16. package/helpers/GlossaryHelper.ts +4 -4
  17. package/helpers/tinymce/plugin.ts +99 -4
  18. package/i18n/en-US/components/content/blocks/feedback.ts +3 -0
  19. package/i18n/en-US/components/index.ts +0 -1
  20. package/i18n/en-US/components/navigation/ask_the_expert.ts +11 -0
  21. package/i18n/en-US/components/navigation/index.ts +2 -0
  22. package/i18n/en-US/components/utils/FillInBlank/FillInBlankInput.ts +13 -0
  23. package/i18n/en-US/components/utils/FillInBlank/FillInTheBlanksManager.ts +11 -0
  24. package/i18n/en-US/components/utils/FillInBlank/index.ts +6 -0
  25. package/i18n/en-US/components/utils/index.ts +2 -1
  26. package/i18n/en-US/components/utils/tiny_mce_wrapper.ts +1 -0
  27. package/i18n/en-US/shared/menu.ts +1 -0
  28. package/i18n/es-ES/components/content/blocks/feedback.ts +29 -0
  29. package/i18n/es-ES/components/content/blocks/image.ts +5 -0
  30. package/i18n/es-ES/components/content/blocks/index.ts +15 -0
  31. package/i18n/es-ES/components/content/blocks/tab.ts +4 -0
  32. package/i18n/es-ES/components/content/blocks/table.ts +4 -0
  33. package/i18n/es-ES/components/content/blocks/user_upload.ts +13 -0
  34. package/i18n/es-ES/components/content/blocks/video.ts +55 -0
  35. package/i18n/es-ES/components/content/index.ts +5 -0
  36. package/i18n/es-ES/components/index.ts +12 -0
  37. package/i18n/es-ES/components/navigation/ask_the_expert.ts +11 -0
  38. package/i18n/es-ES/components/navigation/image.ts +4 -0
  39. package/i18n/es-ES/components/navigation/index.ts +7 -0
  40. package/i18n/es-ES/components/navigation/user_upload.ts +3 -0
  41. package/i18n/es-ES/components/settings/clickable_icon.ts +10 -0
  42. package/i18n/es-ES/components/settings/image.ts +1 -0
  43. package/i18n/es-ES/components/settings/index.ts +13 -0
  44. package/i18n/es-ES/components/settings/text_editor.ts +7 -0
  45. package/i18n/es-ES/components/settings/user_upload.ts +11 -0
  46. package/i18n/es-ES/components/settings/video.ts +13 -0
  47. package/i18n/es-ES/components/utils/index.ts +5 -0
  48. package/i18n/es-ES/components/utils/tiny_mce_wrapper.ts +18 -0
  49. package/i18n/es-ES/index.ts +16 -0
  50. package/i18n/es-ES/modules/index.ts +5 -0
  51. package/i18n/es-ES/pages/glossary.ts +7 -0
  52. package/i18n/es-ES/pages/index.ts +7 -0
  53. package/i18n/es-ES/pages/user_upload.ts +3 -0
  54. package/i18n/es-ES/shared/content_blocks.ts +20 -0
  55. package/i18n/es-ES/shared/index.ts +11 -0
  56. package/i18n/es-ES/shared/menu.ts +3 -0
  57. package/i18n/es-ES/shared/permission.ts +15 -0
  58. package/i18n/es-ES/shared/settings.ts +16 -0
  59. package/i18n/sv-SE/components/content/blocks/feedback.ts +29 -0
  60. package/i18n/sv-SE/components/content/blocks/image.ts +5 -0
  61. package/i18n/sv-SE/components/content/blocks/index.ts +15 -0
  62. package/i18n/sv-SE/components/content/blocks/tab.ts +4 -0
  63. package/i18n/sv-SE/components/content/blocks/table.ts +4 -0
  64. package/i18n/sv-SE/components/content/blocks/user_upload.ts +13 -0
  65. package/i18n/sv-SE/components/content/blocks/video.ts +53 -0
  66. package/i18n/sv-SE/components/content/index.ts +5 -0
  67. package/i18n/sv-SE/components/index.ts +12 -0
  68. package/i18n/sv-SE/components/navigation/ask_the_expert.ts +11 -0
  69. package/i18n/sv-SE/components/navigation/image.ts +4 -0
  70. package/i18n/sv-SE/components/navigation/index.ts +7 -0
  71. package/i18n/sv-SE/components/navigation/user_upload.ts +3 -0
  72. package/i18n/sv-SE/components/settings/clickable_icon.ts +10 -0
  73. package/i18n/sv-SE/components/settings/image.ts +1 -0
  74. package/i18n/sv-SE/components/settings/index.ts +13 -0
  75. package/i18n/sv-SE/components/settings/text_editor.ts +7 -0
  76. package/i18n/sv-SE/components/settings/user_upload.ts +11 -0
  77. package/i18n/sv-SE/components/settings/video.ts +13 -0
  78. package/i18n/sv-SE/components/utils/index.ts +5 -0
  79. package/i18n/sv-SE/components/utils/tiny_mce_wrapper.ts +18 -0
  80. package/i18n/sv-SE/index.ts +16 -0
  81. package/i18n/sv-SE/modules/index.ts +5 -0
  82. package/i18n/sv-SE/pages/glossary.ts +7 -0
  83. package/i18n/sv-SE/pages/index.ts +7 -0
  84. package/i18n/sv-SE/pages/user_upload.ts +3 -0
  85. package/i18n/sv-SE/shared/content_blocks.ts +20 -0
  86. package/i18n/sv-SE/shared/index.ts +11 -0
  87. package/i18n/sv-SE/shared/menu.ts +3 -0
  88. package/i18n/sv-SE/shared/permission.ts +15 -0
  89. package/i18n/sv-SE/shared/settings.ts +15 -0
  90. package/package.json +1 -1
  91. package/plugin.js +25 -0
@@ -0,0 +1,98 @@
1
+ <template>
2
+ <v-container>
3
+ <v-row align="center" justify="center">
4
+ <v-col>
5
+ <v-row align="center" justify="center">
6
+ <v-text-field
7
+ class="col-10"
8
+ :label="
9
+ $t(
10
+ 'windward.core.components.utils.fill_in_the_blank.fill_in_the_blank_manager.answer'
11
+ )
12
+ "
13
+ v-model="answer"
14
+ outlined
15
+ @input="submit"
16
+ ></v-text-field>
17
+ </v-row>
18
+
19
+ <br />
20
+
21
+ <v-row align="center" justify="center">
22
+ <TextEditor
23
+ :key="key"
24
+ v-model="feedback"
25
+ @input="submit"
26
+ ></TextEditor>
27
+ </v-row>
28
+ </v-col>
29
+ </v-row>
30
+ </v-container>
31
+ </template>
32
+ <script>
33
+ import TextEditor from '~/components/Text/TextEditor.vue'
34
+ import _ from 'lodash'
35
+ import Crypto from '~/helpers/Crypto'
36
+ export default {
37
+ name: 'FillInTheBlanksManager',
38
+ components: { TextEditor },
39
+ data() {
40
+ return {
41
+ answer: '',
42
+ feedback: '',
43
+ key: '',
44
+ }
45
+ },
46
+ mounted() {
47
+ window.parent.postMessage(
48
+ {
49
+ mceAction: 'fib-plugin-mounted',
50
+ status: true,
51
+ },
52
+ '*'
53
+ )
54
+ },
55
+ created() {
56
+ window.parent.addEventListener('message', (event) => {
57
+ if (event.data.answer)
58
+ this.init({
59
+ answer: event.data.answer,
60
+ feedback: event.data.feedback,
61
+ })
62
+ })
63
+ },
64
+
65
+ computed: {},
66
+
67
+ methods: {
68
+ init(data) {
69
+ this.answer = data.answer
70
+ this.feedback = _.cloneDeep(
71
+ atob(data.feedback ? data.feedback : 'empty')
72
+ )
73
+ this.key = Crypto.id()
74
+ },
75
+ submit() {
76
+ window.parent.postMessage(
77
+ {
78
+ mceAction: 'fib-insert',
79
+ content: {
80
+ answer: this.answer,
81
+ feedback: btoa(this.feedback),
82
+ },
83
+ },
84
+ '*'
85
+ )
86
+ },
87
+ },
88
+ }
89
+ </script>
90
+ <style scoped>
91
+ .correct,
92
+ p {
93
+ background: #7c7;
94
+ }
95
+
96
+ .answer {
97
+ }
98
+ </style>
@@ -60,13 +60,13 @@
60
60
  primary
61
61
  color="success"
62
62
  @click="setSRText"
63
- :class="shrinkClass"
63
+ :class="fontSize"
64
64
  >{{ $t('shared.accessibility.default_text') }}
65
65
  </v-btn>
66
66
  <v-btn
67
67
  :disabled="spokenTextChanged"
68
68
  color="primary"
69
- :class="shrinkClass"
69
+ :class="fontSize"
70
70
  @click="readSRText"
71
71
  >{{
72
72
  $t(
@@ -140,7 +140,6 @@ export default {
140
140
  tab: null,
141
141
  toggle_exclusive: true,
142
142
  panel: [],
143
- shrinkClass: '',
144
143
  }
145
144
  },
146
145
  computed: {
@@ -151,6 +150,12 @@ export default {
151
150
 
152
151
  return plugin[0]
153
152
  },
153
+ fontSize() {
154
+ if (this.shrinkFont === true) {
155
+ return 'adjustFont'
156
+ }
157
+ return ''
158
+ },
154
159
  },
155
160
  beforeMount() {
156
161
  if (this.mode === 'standalone') {
@@ -158,9 +163,6 @@ export default {
158
163
  }
159
164
  },
160
165
  mounted() {
161
- if (this.shrinkFont === true) {
162
- this.shrinkClass = 'adjustFont'
163
- }
164
166
  if (this.mode === 'plugin') {
165
167
  window.parent.postMessage(
166
168
  {
@@ -14,7 +14,7 @@
14
14
  <script>
15
15
  import _ from 'lodash'
16
16
  import Editor from '@tinymce/tinymce-vue'
17
- import { MathEditorPlugin } from '../../helpers/tinymce/plugin'
17
+ import { WindwardPlugins } from '../../helpers/tinymce/plugin'
18
18
  import contentCss from '!raw-loader!sass-loader!./assets/tinymce/css/content.scss'
19
19
  import Crypto from '~/helpers/Crypto'
20
20
  export default {
@@ -50,11 +50,11 @@ export default {
50
50
  return {
51
51
  height: 500,
52
52
  visual: false,
53
- menubar: 'file edit insert format view table help',
53
+ menubar: 'file edit insert format view table windward help',
54
54
  menu: {
55
55
  insert: {
56
56
  title: 'Insert',
57
- items: ' link inserttable | charmap | anchor | math | insertdatetime',
57
+ items: ' link inserttable | charmap | anchor | math | FIB | insertdatetime',
58
58
  },
59
59
  table: {
60
60
  title: 'Table',
@@ -65,10 +65,10 @@ export default {
65
65
  'advlist autolink lists link charmap',
66
66
  'searchreplace visualblocks code fullscreen',
67
67
  'anchor insertdatetime ',
68
- 'paste code wordcount table MathEditor ',
68
+ 'paste code wordcount table WindwardToolKit ',
69
69
  ],
70
70
  toolbar:
71
- 'undo redo | formatselect | bold italic | alignleft aligncenter alignright | table bullist numlist outdent indent | mathButton',
71
+ 'undo redo | formatselect | bold italic | alignleft aligncenter alignright | table bullist numlist outdent indent | mathButton ',
72
72
  table_advtab: false,
73
73
  table_cell_advtab: false,
74
74
  table_row_advtab: false,
@@ -149,8 +149,8 @@ export default {
149
149
  setup() {
150
150
  // Here we can add plugin
151
151
  window.tinymce.PluginManager.add(
152
- 'MathEditor',
153
- MathEditorPlugin
152
+ 'WindwardToolKit',
153
+ WindwardPlugins
154
154
  )
155
155
  },
156
156
  formats: {
@@ -163,6 +163,21 @@ export default {
163
163
  },
164
164
  classes: 'glossary-word',
165
165
  },
166
+ fib: {
167
+ title: this.$t(
168
+ 'windward.core.components.utils.tiny_mce_wrapper.fill_blank'
169
+ ),
170
+ inline: 'span',
171
+ classes: 'windward-fill-blank',
172
+ attributes: {
173
+ contenteditable: 'true',
174
+ 'data-feedback': btoa(
175
+ this.$t(
176
+ 'windward.core.components.utils.fill_in_the_blank.fill_in_blank_input.default.description'
177
+ )
178
+ ),
179
+ },
180
+ },
166
181
  removeformat: [
167
182
  // Configures `clear formatting` to remove the class glossary-word from spans and if the element then becomes empty it's left intact
168
183
  {
@@ -170,15 +185,30 @@ export default {
170
185
  classes: 'glossary-word',
171
186
  remove: 'all',
172
187
  },
188
+ {
189
+ selector: 'span',
190
+ classes: 'windward-fill-blank',
191
+ remove: 'all',
192
+ split: true,
193
+ expand: false,
194
+ deep: true,
195
+ },
173
196
  ],
174
197
  },
175
198
  style_formats: [
199
+ { title: 'Windward formats' },
176
200
  {
177
201
  title: this.$t(
178
202
  'windward.core.components.utils.tiny_mce_wrapper.term'
179
203
  ),
180
204
  format: 'glossary',
181
205
  },
206
+ {
207
+ title: this.$t(
208
+ 'windward.core.components.utils.tiny_mce_wrapper.fill_blank'
209
+ ),
210
+ format: 'fib',
211
+ },
182
212
  ],
183
213
  style_formats_merge: true,
184
214
  placeholder: this.$t(
@@ -188,7 +218,17 @@ export default {
188
218
 
189
219
  skin: this.$vuetify.theme.isDark ? 'oxide-dark' : 'oxide',
190
220
  content_css: this.$vuetify.theme.isDark ? 'dark' : 'default',
191
- content_style: contentCss,
221
+ //we need to inject the glossary style directly
222
+ content_style:
223
+ contentCss +
224
+ ' .glossary-word {\n' +
225
+ ' display: inline-block;\n' +
226
+ ' border-radius: 12px;\n' +
227
+ ' padding: 0px 7px;\n' +
228
+ ' background-color: #ffd269;\n ' +
229
+ ' font-weight: bold;\n' +
230
+ ' color: #1a1d1e;' +
231
+ '}',
192
232
  importcss_append: true,
193
233
  }
194
234
  },
@@ -183,6 +183,15 @@ table {
183
183
  }
184
184
  }
185
185
 
186
+ span.windward-fill-blank{
187
+ display: inline-block;
188
+ cursor: pointer;
189
+ border: 2px solid #206e8c;
190
+ border-radius: 5px;
191
+ padding: 2px 5px;
192
+ margin: 0 2px;
193
+ color: #000000;
194
+ }
186
195
 
187
196
 
188
197
 
@@ -140,14 +140,14 @@ export default {
140
140
  {
141
141
  text: this.$t('windward.core.pages.glossary.term'),
142
142
  align: 'start',
143
- sortable: false,
144
- value: 'glossaryTerms.term',
143
+ sortable: true,
144
+ value: 'term',
145
145
  },
146
146
  {
147
147
  text: this.$t('windward.core.pages.glossary.definition'),
148
148
  align: 'start',
149
149
  sortable: true,
150
- value: 'glossaryTerms.definition',
150
+ value: 'definition',
151
151
  },
152
152
  {
153
153
  text: this.$t(
@@ -155,13 +155,13 @@ export default {
155
155
  ),
156
156
  align: 'start',
157
157
  sortable: true,
158
- value: 'glossaryTerms.alternate_forms',
158
+ value: 'alternate_forms',
159
159
  },
160
160
  {
161
161
  text: this.$t('windward.core.pages.glossary.related_term'),
162
162
  align: 'start',
163
163
  sortable: true,
164
- value: 'glossaryTerms.related_term',
164
+ value: 'related_term',
165
165
  },
166
166
  ],
167
167
  dialog: false,
@@ -207,12 +207,16 @@ export default {
207
207
  } else {
208
208
  this.glossaryTerms.push(this.selectedTerm)
209
209
  }
210
- const course = new Course(this.course)
211
- if (!_.isSet(course.metadata)) {
210
+ const course = new Course(_.cloneDeep(this.course))
211
+ if (
212
+ !course.hasOwnProperty('metadata') ||
213
+ course.metadata === null
214
+ ) {
212
215
  course.metadata = {}
213
216
  course.metadata.glossary = {}
214
217
  }
215
- if (!_.isSet(course.metadata.glossary)) {
218
+
219
+ if (course.metadata.glossary !== undefined) {
216
220
  course.metadata.glossary = this.glossaryTerms
217
221
  }
218
222
  const updatedCourse = await course.save()
@@ -10,19 +10,31 @@
10
10
  <br />
11
11
  <v-textarea
12
12
  v-model="selectedTerm.definition"
13
- :counter="255"
14
13
  :label="$t('windward.core.pages.glossary.definition')"
15
14
  outlined
16
15
  required
17
16
  :rules="validation.definitionRules"
18
17
  ></v-textarea>
19
18
  <br />
20
- <v-textarea
19
+ <v-combobox
21
20
  v-model="selectedTerm.alternate_forms"
22
- :counter="50"
21
+ chips
22
+ clearable
23
23
  :label="$t('windward.core.pages.glossary.alternate_forms')"
24
- outlined
25
- ></v-textarea>
24
+ multiple
25
+ solo
26
+ >
27
+ <template v-slot:selection="{ attrs, item, select, selected }">
28
+ <v-chip
29
+ v-bind="attrs"
30
+ :input-value="selected"
31
+ close
32
+ @click:close="removeAlternateForm(item)"
33
+ >
34
+ <strong>{{ item }}</strong>
35
+ </v-chip>
36
+ </template>
37
+ </v-combobox>
26
38
  <br />
27
39
  <v-select
28
40
  v-model="selectedTerm.related_term"
@@ -97,6 +109,13 @@ export default {
97
109
  return true
98
110
  }
99
111
  },
112
+ removeAlternateForm(form) {
113
+ const index = this.selectedTerm.alternate_forms.indexOf(form)
114
+ if (index > -1) {
115
+ // only splice array when item is found
116
+ this.selectedTerm.alternate_forms.splice(index, 1) // 2nd parameter means remove one item only
117
+ }
118
+ },
100
119
  },
101
120
  }
102
121
  </script>
@@ -0,0 +1,55 @@
1
+ import * as _ from "lodash";
2
+ import GlossaryTerm from "~/helpers/GlossaryTerm";
3
+
4
+ export default class FillInBlankHelper {
5
+
6
+ private static FillBlankRegex = /<span.*?.class="windward-fill-blank".*?>(.*?)<\/span>/gi;
7
+
8
+ public static containsFillInBlank(content: string): boolean {
9
+ const regex = new RegExp(this.FillBlankRegex);
10
+
11
+ return regex.exec(content) !== null;
12
+ }
13
+
14
+ public static makeToolTip(htmlString: string): string {
15
+ const parser = new DOMParser();
16
+ const doc = parser.parseFromString(htmlString, "text/html");
17
+ // doc.body.firstChild can be null
18
+ let answer = doc.body.firstChild ? doc.body.firstChild.textContent : "";
19
+ let feedback = "";
20
+ if (doc.body.getElementsByClassName("windward-fill-blank")[0]["dataset"]["feedback"] !== undefined) {
21
+ feedback = doc.body.getElementsByClassName("windward-fill-blank")[0]["dataset"]["feedback"];
22
+ }
23
+
24
+ return (
25
+ "<plugin-core-fill-in-blank-input answer=\"" + answer + "\" description=\"" + feedback + "\">" +
26
+ "</template>" + "</plugin-core-fill-in-blank-input>");
27
+
28
+ }
29
+
30
+ public escapeHtml(html) {
31
+ var text = document.createTextNode(html);
32
+ var p = document.createElement("p");
33
+ p.appendChild(text);
34
+ return p.innerHTML;
35
+ }
36
+
37
+ public static renderFillInTHeBlankHtml(content: string, glossary: any) {
38
+ const regex = new RegExp(this.FillBlankRegex);
39
+
40
+
41
+ let match;
42
+ while ((match = regex.exec(content)) !== null) {
43
+ // This is necessary to avoid infinite loops with zero-width matches
44
+ if (match.index === regex.lastIndex) {
45
+ regex.lastIndex++;
46
+ }
47
+ content = content.replace(
48
+ match[0],
49
+ this.makeToolTip(match[0])
50
+ );
51
+ }
52
+
53
+ return content;
54
+ }
55
+ }
@@ -38,13 +38,13 @@ export default class GlossaryHelper {
38
38
 
39
39
  }
40
40
  public static containsGlossaryTerms(content :string): boolean {
41
- const regex = this.glossaryRegex
41
+ const regex = new RegExp(this.glossaryRegex)
42
42
 
43
43
  return regex.exec(content) !== null
44
44
  }
45
45
 
46
46
  public static getContentVerifiedGlossaryTerms(content :string, glossary :any) {
47
- const regex = this.glossaryRegex
47
+ const regex = new RegExp( this.glossaryRegex)
48
48
  const currentGlossary = glossary
49
49
 
50
50
  let match
@@ -74,7 +74,7 @@ export default class GlossaryHelper {
74
74
  }
75
75
 
76
76
  public static getContentUnVerifiedGlossaryTerms(content :string, glossary :any) {
77
- const regex = this.glossaryRegex
77
+ const regex = new RegExp( this.glossaryRegex)
78
78
 
79
79
  let match
80
80
  const verifiedTerms = this.getContentVerifiedGlossaryTerms(content,glossary)
@@ -110,7 +110,7 @@ export default class GlossaryHelper {
110
110
  return unVerifiedTerms
111
111
  }
112
112
  public static renderGlossaryWordsHtml(content :string, glossary :any) {
113
- const regex = this.glossaryRegex
113
+ const regex = new RegExp( this.glossaryRegex)
114
114
  const currentGlossary = glossary
115
115
 
116
116
  let match
@@ -1,5 +1,6 @@
1
- const MathEditorPlugin = function (editor: any) {
1
+ const WindwardPlugins = function (editor: any) {
2
2
  let formula: any
3
+ let fillInBlank: any
3
4
  // ----- Events ----- //
4
5
  editor.ui.registry.addIcon('insertMath', '<svg x="0px" y="0px"width="20px" height="20px" viewBox="0 0 445.878 445.878" style="enable-background:new 0 0 445.878 445.878;">' +
5
6
  '<path d="M426.024,86.447H209.705l-84.911,298.911c-2.568,7.967-9.854,13.482-18.22,13.771c-0.236,0-0.464,0.006-0.688,0.006 c-8.092,0-15.41-4.924-18.436-12.478l-34.714-86.782H19.851C8.884,299.876,0,290.986,0,280.022 c0-10.965,8.893-19.854,19.851-19.854H66.18c8.109,0,15.421,4.941,18.436,12.483l19.237,48.09l72.472-260.218 c2.639-8.213,10.279-13.781,18.903-13.781h230.798c10.97,0,19.854,8.89,19.854,19.851S436.988,86.447,426.024,86.447z M436.723,353.227l-78.259-87.904l74.576-82.783c1.318-1.454,1.638-3.547,0.857-5.341c-0.804-1.791-2.577-2.946-4.54-2.946h-47.18 c-1.442,0-2.802,0.629-3.759,1.72l-50.059,58.047l-49.674-58.029c-0.939-1.103-2.317-1.738-3.771-1.738h-49.334 c-1.956,0-3.729,1.149-4.521,2.929c-0.81,1.785 0.479,3.875,0.824,5.332l73.743,82.81l-77.641,87.923 c-1.297,1.465-1.605,3.552 0.813,5.325c0.813,1.785,2.586,2.92,4.528,2.92h48.9c1.472,0,2.867-0.65,3.807-1.785l51.819-62.181 l53.05,62.229c0.951,1.11,2.328,1.743,3.782,1.743h49.97c1.962,0,3.735-1.141,4.527-2.926 C438.354,356.779,438.035,354.692,436.723,353.227z"/>' +
@@ -41,7 +42,7 @@ const MathEditorPlugin = function (editor: any) {
41
42
  formula = message.content
42
43
  break
43
44
  case 'math-plugin-mounted':
44
- window.parent.postMessage({ latex: data.latex }, '*')
45
+ window.postMessage({ latex: data.latex ?? '' }, '*')
45
46
  break
46
47
  }
47
48
  },
@@ -63,6 +64,11 @@ const MathEditorPlugin = function (editor: any) {
63
64
  })
64
65
  editor.on('init', function () {
65
66
  setOnClickEquationContent(editor)
67
+ setOnClickFillInBlank(editor)
68
+ })
69
+ editor.on('change', function () {
70
+ setOnClickEquationContent(editor)
71
+ setOnClickFillInBlank(editor)
66
72
  })
67
73
  function setOnClickEquationContent(editor: any) {
68
74
  const tinymceDoc = editor.getDoc()
@@ -86,7 +92,96 @@ const MathEditorPlugin = function (editor: any) {
86
92
  }
87
93
  }
88
94
  }
89
- }
90
95
 
91
96
 
92
- export { MathEditorPlugin }
97
+ editor.addCommand('fib-window', function (data: any) {
98
+
99
+ return editor.windowManager.openUrl({
100
+ url: '/plugins/tinymce/FIB',
101
+ title: 'Fill in the blank',
102
+ width: 1024,
103
+ height: 768,
104
+ buttons: [
105
+ {
106
+ type: 'cancel',
107
+ text: 'cancel',
108
+ },
109
+ {
110
+ type: 'custom',
111
+ text: 'submit',
112
+ primary: true,
113
+ },
114
+ ],
115
+ onAction: () => {
116
+ if (data.currentTarget) {
117
+ editor.selection.select(data.currentTarget);
118
+ }
119
+ editor.selection.setContent(
120
+ `<span class='windward-fill-blank' data-feedback =`+ fillInBlank.feedback +` >` +
121
+ fillInBlank.answer +
122
+ `</span>`
123
+ )
124
+
125
+ editor.windowManager.close()
126
+ setOnClickFillInBlank(editor);
127
+ },
128
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
129
+ onMessage: (instance: any, message: any) => {
130
+ switch (message.mceAction) {
131
+ case 'fib-insert':
132
+ fillInBlank = { answer: message.content.answer, feedback: message.content.feedback }
133
+ break
134
+ case 'fib-plugin-mounted':
135
+ window.parent.postMessage({ answer: data.answer ,
136
+ feedback: data.feedback, }, '*')
137
+ break
138
+ }
139
+ },
140
+ })
141
+ })
142
+
143
+ editor.ui.registry.addIcon('insertFIB', '<svg width="20px" height="20px" viewBox="0 0 24 24"><path d="M17,7H22V17H17V19A1,1 0 0,0 18,20H20V22H17.5C16.95,22 16,21.55 16,21C16,21.55 15.05,22 14.5,22H12V20H14A1,1 0 0,0 15,19V5A1,1 0 0,0 14,4H12V2H14.5C15.05,2 16,2.45 16,3C16,2.45 16.95,2 17.5,2H20V4H18A1,1 0 0,0 17,5V7M2,7H13V9H4V15H13V17H2V7M20,15V9H17V15H20Z" /></svg>' );
144
+ /* Add a button that opens a window */
145
+ editor.ui.registry.addButton('fibButton', {
146
+ icon: 'insertFIB',
147
+ onAction: function () {
148
+ /* Open window */
149
+ editor.execCommand('fib-window', true)
150
+
151
+ }
152
+ });
153
+ editor.ui.registry.addMenuItem('FIB', {
154
+ text: 'FIll in the blank',
155
+ icon: 'insertFIB',
156
+ onAction: () => {
157
+ editor.execCommand('fib-window', true)
158
+ },
159
+ })
160
+
161
+ function setOnClickFillInBlank(editor: any) {
162
+ const tinymceDoc = editor.getDoc()
163
+ const mqSpan = tinymceDoc.getElementsByClassName(
164
+ 'windward-fill-blank'
165
+ )
166
+
167
+ // Add onclick listener to all equation content
168
+ for (const fib of mqSpan) {
169
+ fib.contentEditable = 'true'
170
+ if (fib.onclick) {
171
+ continue
172
+ }
173
+
174
+ fib.onclick = (event: any) => {
175
+ event.stopPropagation()
176
+ editor.execCommand('fib-window', {
177
+ answer: event.target.innerText,
178
+ feedback: event.target.getAttribute('data-feedback'),
179
+ currentTarget: event.target,
180
+ })
181
+ }
182
+ }
183
+ }
184
+
185
+ }
186
+
187
+ export { WindwardPlugins }
@@ -4,6 +4,8 @@ export default {
4
4
  module: 'Module',
5
5
  preset: 'Presets',
6
6
  likert: 'Add standart likert questions',
7
+ likert_directions:
8
+ 'Click to choose first option and then use tab to switch button groups and then arrows to navigate between options.',
7
9
  contact_mindedge: 'Contact Mindedge question',
8
10
  open_response: 'Open Response',
9
11
  response_prompt: 'Provide course feedback below',
@@ -14,6 +16,7 @@ export default {
14
16
  fill_out: 'Please fill out all fields',
15
17
  yes: 'Yes',
16
18
  no: 'No',
19
+ enter: 'Enter Text',
17
20
  description:
18
21
  "This feedback form is optional. However, we would love to hear your thoughts on this learning experience. We take your feedback very seriously, reading and reviewing each entry every day, and we are always trying to improve. Thank you for any comments you'd like to share.",
19
22
  sent_feedback:
@@ -3,7 +3,6 @@ import settings from './settings'
3
3
  import navigation from './navigation/index'
4
4
  import utils from './utils/index'
5
5
 
6
-
7
6
  export default {
8
7
  content,
9
8
  settings,
@@ -0,0 +1,11 @@
1
+ export default {
2
+ ask_expert: 'Ask the Expert',
3
+ config: 'Configuration',
4
+ recipient_email: 'Recipient Email',
5
+ course_info: 'Course and Page Name',
6
+ student_section: 'Student Section',
7
+ subject: 'Subject',
8
+ question: 'Question',
9
+ description:
10
+ 'Ask an expert a question that is specific to the course content',
11
+ }
@@ -1,7 +1,9 @@
1
+ import ask_the_expert from './ask_the_expert'
1
2
  import user_upload from './user_upload'
2
3
  import image from './image'
3
4
 
4
5
  export default {
5
6
  user_upload,
6
7
  image,
8
+ ask_the_expert,
7
9
  }
@@ -0,0 +1,13 @@
1
+ export default {
2
+ add_answer: 'Add Answer',
3
+ answer: 'Answer',
4
+ check: 'Check',
5
+ check_answer: 'Click to check answer',
6
+ close: 'Close',
7
+ correct: 'Correct',
8
+ default_description: 'default description',
9
+ incorrect: 'Incorrect',
10
+ input_incorrect: "'{0}' is incorrect",
11
+ reset: 'reset',
12
+ try_again: 'Try Again',
13
+ }
@@ -0,0 +1,11 @@
1
+ export default {
2
+ close: 'Close',
3
+ try_again: 'Try Again',
4
+ correct: 'Correct',
5
+ incorrect: 'Incorrect',
6
+ reset: 'reset',
7
+ check: 'Check',
8
+ add_answer: 'Add Answer',
9
+ default_description: 'default description',
10
+ answer: 'Answer',
11
+ }