@windward/core 0.0.6 → 0.0.8

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 (154) hide show
  1. package/.idea/codeStyles/Project.xml +58 -0
  2. package/.idea/codeStyles/codeStyleConfig.xml +5 -0
  3. package/.idea/inspectionProfiles/Project_Default.xml +6 -0
  4. package/.idea/modules.xml +8 -0
  5. package/.idea/php-docker-settings.xml +24 -0
  6. package/.idea/php.xml +19 -0
  7. package/.idea/vcs.xml +6 -0
  8. package/.idea/watcherTasks.xml +4 -0
  9. package/.idea/windward-ui-plugin-core.iml +8 -0
  10. package/components/Content/Blocks/Image.vue +36 -14
  11. package/components/Content/Blocks/OpenResponse.vue +159 -0
  12. package/components/Content/Blocks/OpenResponseCollate.vue +185 -0
  13. package/components/Settings/ImageSettings.vue +10 -0
  14. package/components/Settings/OpenResponseCollateSettings.vue +171 -0
  15. package/components/Settings/OpenResponseSettings.vue +81 -0
  16. package/components/Settings/TextEditorSettings.vue +1 -0
  17. package/components/utils/TinyMCEWrapper.vue +21 -4
  18. package/components/utils/assets/tinymce/css/content.scss +1 -1
  19. package/coverage/clover.xml +223 -0
  20. package/coverage/coverage-final.json +16 -0
  21. package/coverage/lcov-report/base.css +224 -0
  22. package/coverage/lcov-report/block-navigation.js +87 -0
  23. package/coverage/lcov-report/components/Content/Blocks/Accordion.vue.html +430 -0
  24. package/coverage/lcov-report/components/Content/Blocks/Image.vue.html +394 -0
  25. package/coverage/lcov-report/components/Content/Blocks/Math.vue.html +262 -0
  26. package/coverage/lcov-report/components/Content/Blocks/RichText.vue.html +295 -0
  27. package/coverage/lcov-report/components/Content/Blocks/Tab.vue.html +415 -0
  28. package/coverage/lcov-report/components/Content/Blocks/Table.vue.html +667 -0
  29. package/coverage/lcov-report/components/Content/Blocks/Video.vue.html +2275 -0
  30. package/coverage/lcov-report/components/Content/Blocks/index.html +206 -0
  31. package/coverage/lcov-report/components/utils/ContentViewer.vue.html +199 -0
  32. package/coverage/lcov-report/components/utils/MathExpressionEditor.vue.html +919 -0
  33. package/coverage/lcov-report/components/utils/MathLiveWrapper.vue.html +343 -0
  34. package/coverage/lcov-report/components/utils/TinyMCEWrapper.vue.html +271 -0
  35. package/coverage/lcov-report/components/utils/index.html +161 -0
  36. package/coverage/lcov-report/config/index.html +116 -0
  37. package/coverage/lcov-report/config/tinymce.config.js.html +493 -0
  38. package/coverage/lcov-report/favicon.png +0 -0
  39. package/coverage/lcov-report/helpers/MathHelper.ts.html +793 -0
  40. package/coverage/lcov-report/helpers/index.html +116 -0
  41. package/coverage/lcov-report/helpers/tinymce/index.html +116 -0
  42. package/coverage/lcov-report/helpers/tinymce/plugin.ts.html +334 -0
  43. package/coverage/lcov-report/index.html +191 -0
  44. package/coverage/lcov-report/prettify.css +1 -0
  45. package/coverage/lcov-report/prettify.js +2 -0
  46. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  47. package/coverage/lcov-report/sorter.js +196 -0
  48. package/coverage/lcov-report/test/index.html +116 -0
  49. package/coverage/lcov-report/test/mocks.js.html +457 -0
  50. package/coverage/lcov.info +403 -0
  51. package/helpers/tinymce/plugin.ts +1 -1
  52. package/i18n/en-US/components/content/blocks/index.ts +4 -0
  53. package/i18n/en-US/components/content/blocks/open_response.ts +5 -0
  54. package/i18n/en-US/components/content/blocks/open_response_collate.ts +7 -0
  55. package/i18n/en-US/components/settings/image.ts +3 -1
  56. package/i18n/en-US/components/settings/index.ts +5 -1
  57. package/i18n/en-US/components/settings/open_response.ts +5 -0
  58. package/i18n/en-US/components/settings/open_response_collate.ts +6 -0
  59. package/i18n/en-US/shared/content_blocks.ts +2 -0
  60. package/i18n/en-US/shared/settings.ts +3 -1
  61. package/i18n/es-ES/components/content/blocks/index.ts +4 -0
  62. package/i18n/es-ES/components/content/blocks/open_response.ts +6 -0
  63. package/i18n/es-ES/components/content/blocks/open_response_collate.ts +7 -0
  64. package/i18n/es-ES/components/settings/image.ts +3 -1
  65. package/i18n/es-ES/components/settings/index.ts +4 -0
  66. package/i18n/es-ES/components/settings/open_response.ts +5 -0
  67. package/i18n/es-ES/components/settings/open_response_collate.ts +7 -0
  68. package/i18n/es-ES/shared/content_blocks.ts +2 -0
  69. package/i18n/es-ES/shared/settings.ts +3 -0
  70. package/i18n/sv-SE/components/content/blocks/index.ts +4 -0
  71. package/i18n/sv-SE/components/content/blocks/open_response.ts +6 -0
  72. package/i18n/sv-SE/components/content/blocks/open_response_collate.ts +7 -0
  73. package/i18n/sv-SE/components/settings/image.ts +3 -1
  74. package/i18n/sv-SE/components/settings/index.ts +5 -1
  75. package/i18n/sv-SE/components/settings/open_response.ts +5 -0
  76. package/i18n/sv-SE/components/settings/open_response_collate.ts +6 -0
  77. package/i18n/sv-SE/shared/content_blocks.ts +2 -0
  78. package/i18n/sv-SE/shared/settings.ts +2 -0
  79. package/lib/helpers/GlossaryHelper.d.ts +9 -0
  80. package/lib/helpers/GlossaryHelper.js +118 -0
  81. package/lib/helpers/GlossaryTerm.d.ts +10 -0
  82. package/lib/helpers/GlossaryTerm.js +22 -0
  83. package/lib/helpers/MathHelper.d.ts +99 -0
  84. package/lib/helpers/MathHelper.js +194 -0
  85. package/lib/helpers/tinymce/plugin.d.ts +2 -0
  86. package/lib/helpers/tinymce/plugin.js +86 -0
  87. package/lib/i18n/en-US/components/content/blocks/image.d.ts +6 -0
  88. package/lib/i18n/en-US/components/content/blocks/image.js +7 -0
  89. package/lib/i18n/en-US/components/content/blocks/index.d.ts +75 -0
  90. package/lib/i18n/en-US/components/content/blocks/index.js +14 -0
  91. package/lib/i18n/en-US/components/content/blocks/tab.d.ts +5 -0
  92. package/lib/i18n/en-US/components/content/blocks/tab.js +6 -0
  93. package/lib/i18n/en-US/components/content/blocks/table.d.ts +5 -0
  94. package/lib/i18n/en-US/components/content/blocks/table.js +6 -0
  95. package/lib/i18n/en-US/components/content/blocks/user_upload.d.ts +13 -0
  96. package/lib/i18n/en-US/components/content/blocks/user_upload.js +14 -0
  97. package/lib/i18n/en-US/components/content/blocks/video.d.ts +48 -0
  98. package/lib/i18n/en-US/components/content/blocks/video.js +49 -0
  99. package/lib/i18n/en-US/components/content/index.d.ts +77 -0
  100. package/lib/i18n/en-US/components/content/index.js +6 -0
  101. package/lib/i18n/en-US/components/index.d.ts +140 -0
  102. package/lib/i18n/en-US/components/index.js +12 -0
  103. package/lib/i18n/en-US/components/navigation/image.d.ts +5 -0
  104. package/lib/i18n/en-US/components/navigation/image.js +6 -0
  105. package/lib/i18n/en-US/components/navigation/index.d.ts +10 -0
  106. package/lib/i18n/en-US/components/navigation/index.js +8 -0
  107. package/lib/i18n/en-US/components/navigation/user_upload.d.ts +4 -0
  108. package/lib/i18n/en-US/components/navigation/user_upload.js +5 -0
  109. package/lib/i18n/en-US/components/settings/clickable_icon.d.ts +6 -0
  110. package/lib/i18n/en-US/components/settings/clickable_icon.js +7 -0
  111. package/lib/i18n/en-US/components/settings/image.d.ts +2 -0
  112. package/lib/i18n/en-US/components/settings/image.js +3 -0
  113. package/lib/i18n/en-US/components/settings/index.d.ts +39 -0
  114. package/lib/i18n/en-US/components/settings/index.js +14 -0
  115. package/lib/i18n/en-US/components/settings/text_editor.d.ts +8 -0
  116. package/lib/i18n/en-US/components/settings/text_editor.js +9 -0
  117. package/lib/i18n/en-US/components/settings/user_upload.d.ts +12 -0
  118. package/lib/i18n/en-US/components/settings/user_upload.js +13 -0
  119. package/lib/i18n/en-US/components/settings/video.d.ts +13 -0
  120. package/lib/i18n/en-US/components/settings/video.js +14 -0
  121. package/lib/i18n/en-US/components/utils/index.d.ts +15 -0
  122. package/lib/i18n/en-US/components/utils/index.js +6 -0
  123. package/lib/i18n/en-US/components/utils/tiny_mce_wrapper.d.ts +13 -0
  124. package/lib/i18n/en-US/components/utils/tiny_mce_wrapper.js +14 -0
  125. package/lib/i18n/en-US/index.d.ts +197 -0
  126. package/lib/i18n/en-US/index.js +16 -0
  127. package/lib/i18n/en-US/modules/index.d.ts +2 -0
  128. package/lib/i18n/en-US/modules/index.js +6 -0
  129. package/lib/i18n/en-US/pages/glossary.d.ts +8 -0
  130. package/lib/i18n/en-US/pages/glossary.js +9 -0
  131. package/lib/i18n/en-US/pages/index.d.ts +13 -0
  132. package/lib/i18n/en-US/pages/index.js +8 -0
  133. package/lib/i18n/en-US/pages/user_upload.d.ts +4 -0
  134. package/lib/i18n/en-US/pages/user_upload.js +5 -0
  135. package/lib/i18n/en-US/shared/content_blocks.d.ts +20 -0
  136. package/lib/i18n/en-US/shared/content_blocks.js +21 -0
  137. package/lib/i18n/en-US/shared/index.d.ts +39 -0
  138. package/lib/i18n/en-US/shared/index.js +10 -0
  139. package/lib/i18n/en-US/shared/menu.d.ts +4 -0
  140. package/lib/i18n/en-US/shared/menu.js +5 -0
  141. package/lib/i18n/en-US/shared/settings.d.ts +15 -0
  142. package/lib/i18n/en-US/shared/settings.js +16 -0
  143. package/lib/i18n/en-US.d.ts +197 -0
  144. package/lib/i18n/en-US.js +15 -0
  145. package/lib/models/UserFileAsset.d.ts +5 -0
  146. package/lib/models/UserFileAsset.js +37 -0
  147. package/package.json +1 -1
  148. package/plugin.js +43 -0
  149. package/test/Components/Content/Blocks/OpenResponse.spec.js +31 -0
  150. package/test/Components/Content/Blocks/OpenResponseCollate.spec.js +36 -0
  151. package/test/Components/Settings/OpenResponseCollateSettings.spec.js +20 -0
  152. package/test/Components/Settings/OpenResponseSettings.spec.js +20 -0
  153. package/test/__mocks__/helpersMock.js +3 -0
  154. package/test/__mocks__/modelMock.js +4 -0
@@ -0,0 +1,58 @@
1
+ <component name="ProjectCodeStyleConfiguration">
2
+ <code_scheme name="Project" version="173">
3
+ <HTMLCodeStyleSettings>
4
+ <option name="HTML_SPACE_INSIDE_EMPTY_TAG" value="true" />
5
+ <option name="HTML_ENFORCE_QUOTES" value="true" />
6
+ </HTMLCodeStyleSettings>
7
+ <JSCodeStyleSettings version="0">
8
+ <option name="FORCE_SEMICOLON_STYLE" value="true" />
9
+ <option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" />
10
+ <option name="FORCE_QUOTE_STYlE" value="true" />
11
+ <option name="ENFORCE_TRAILING_COMMA" value="Remove" />
12
+ <option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" />
13
+ <option name="SPACES_WITHIN_IMPORTS" value="true" />
14
+ </JSCodeStyleSettings>
15
+ <TypeScriptCodeStyleSettings version="0">
16
+ <option name="FORCE_SEMICOLON_STYLE" value="true" />
17
+ <option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" />
18
+ <option name="FORCE_QUOTE_STYlE" value="true" />
19
+ <option name="ENFORCE_TRAILING_COMMA" value="Remove" />
20
+ <option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" />
21
+ <option name="SPACES_WITHIN_IMPORTS" value="true" />
22
+ </TypeScriptCodeStyleSettings>
23
+ <VueCodeStyleSettings>
24
+ <option name="INTERPOLATION_NEW_LINE_AFTER_START_DELIMITER" value="false" />
25
+ <option name="INTERPOLATION_NEW_LINE_BEFORE_END_DELIMITER" value="false" />
26
+ </VueCodeStyleSettings>
27
+ <codeStyleSettings language="HTML">
28
+ <option name="SOFT_MARGINS" value="80" />
29
+ <indentOptions>
30
+ <option name="INDENT_SIZE" value="2" />
31
+ <option name="CONTINUATION_INDENT_SIZE" value="2" />
32
+ <option name="TAB_SIZE" value="2" />
33
+ </indentOptions>
34
+ </codeStyleSettings>
35
+ <codeStyleSettings language="JavaScript">
36
+ <option name="SOFT_MARGINS" value="80" />
37
+ <indentOptions>
38
+ <option name="INDENT_SIZE" value="2" />
39
+ <option name="CONTINUATION_INDENT_SIZE" value="2" />
40
+ <option name="TAB_SIZE" value="2" />
41
+ </indentOptions>
42
+ </codeStyleSettings>
43
+ <codeStyleSettings language="TypeScript">
44
+ <option name="SOFT_MARGINS" value="80" />
45
+ <indentOptions>
46
+ <option name="INDENT_SIZE" value="2" />
47
+ <option name="CONTINUATION_INDENT_SIZE" value="2" />
48
+ <option name="TAB_SIZE" value="2" />
49
+ </indentOptions>
50
+ </codeStyleSettings>
51
+ <codeStyleSettings language="Vue">
52
+ <option name="SOFT_MARGINS" value="80" />
53
+ <indentOptions>
54
+ <option name="CONTINUATION_INDENT_SIZE" value="2" />
55
+ </indentOptions>
56
+ </codeStyleSettings>
57
+ </code_scheme>
58
+ </component>
@@ -0,0 +1,5 @@
1
+ <component name="ProjectCodeStyleConfiguration">
2
+ <state>
3
+ <option name="USE_PER_PROJECT_SETTINGS" value="true" />
4
+ </state>
5
+ </component>
@@ -0,0 +1,6 @@
1
+ <component name="InspectionProjectProfileManager">
2
+ <profile version="1.0">
3
+ <option name="myName" value="Project Default" />
4
+ <inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
5
+ </profile>
6
+ </component>
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="ProjectModuleManager">
4
+ <modules>
5
+ <module fileurl="file://$PROJECT_DIR$/.idea/windward-ui-plugin-core.iml" filepath="$PROJECT_DIR$/.idea/windward-ui-plugin-core.iml" />
6
+ </modules>
7
+ </component>
8
+ </project>
@@ -0,0 +1,24 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="PhpDockerContainerSettings">
4
+ <list>
5
+ <map>
6
+ <entry key="79d59a8f-c56c-4789-b96c-e55a326ab125">
7
+ <value>
8
+ <DockerContainerSettings>
9
+ <option name="version" value="1" />
10
+ <option name="volumeBindings">
11
+ <list>
12
+ <DockerVolumeBindingImpl>
13
+ <option name="containerPath" value="/opt/project" />
14
+ <option name="hostPath" value="$PROJECT_DIR$" />
15
+ </DockerVolumeBindingImpl>
16
+ </list>
17
+ </option>
18
+ </DockerContainerSettings>
19
+ </value>
20
+ </entry>
21
+ </map>
22
+ </list>
23
+ </component>
24
+ </project>
package/.idea/php.xml ADDED
@@ -0,0 +1,19 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="MessDetectorOptionsConfiguration">
4
+ <option name="transferred" value="true" />
5
+ </component>
6
+ <component name="PHPCSFixerOptionsConfiguration">
7
+ <option name="transferred" value="true" />
8
+ </component>
9
+ <component name="PHPCodeSnifferOptionsConfiguration">
10
+ <option name="highlightLevel" value="WARNING" />
11
+ <option name="transferred" value="true" />
12
+ </component>
13
+ <component name="PhpStanOptionsConfiguration">
14
+ <option name="transferred" value="true" />
15
+ </component>
16
+ <component name="PsalmOptionsConfiguration">
17
+ <option name="transferred" value="true" />
18
+ </component>
19
+ </project>
package/.idea/vcs.xml ADDED
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="VcsDirectoryMappings">
4
+ <mapping directory="" vcs="Git" />
5
+ </component>
6
+ </project>
@@ -0,0 +1,4 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="ProjectTasksOptions" suppressed-tasks="SCSS" />
4
+ </project>
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <module type="WEB_MODULE" version="4">
3
+ <component name="NewModuleRootManager">
4
+ <content url="file://$MODULE_DIR$" />
5
+ <orderEntry type="inheritedJdk" />
6
+ <orderEntry type="sourceFolder" forTests="false" />
7
+ </component>
8
+ </module>
@@ -1,18 +1,27 @@
1
1
  <template>
2
2
  <div>
3
- <p v-if="!block.body">
4
- <v-img
5
- class="img-holder"
6
- src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTNCyiabrwN6YV6s3Mj5IzREZCnQqqwT4A3Bw&usqp=CAU"
7
- contain
8
- ></v-img>
9
- </p>
3
+ <div v-if="!block.body" class="img-holder">
4
+ <v-skeleton-loader
5
+ height="300px"
6
+ :elevation="2"
7
+ type="image"
8
+ ></v-skeleton-loader>
9
+
10
+ <div class="no-source-overlay">
11
+ <v-icon x-large>mdi-file-question</v-icon><br />
12
+ {{
13
+ $t(
14
+ 'windward.core.components.content.blocks.image.no_image_url'
15
+ )
16
+ }}
17
+ </div>
18
+ </div>
10
19
  <v-responsive :aspect-ratio="aspectRatio">
11
20
  <v-img
12
21
  v-if="block.body"
13
22
  :alt="block.metadata.config.alt"
14
23
  :aria-describedby="block.metadata.config.aria_described_by"
15
- class="img-display"
24
+ :class="imageClass"
16
25
  :src="block.body"
17
26
  contain
18
27
  >
@@ -48,10 +57,10 @@ export default {
48
57
  },
49
58
  data() {
50
59
  return {
60
+ id: 'image_' + Crypto.id(),
51
61
  aspectRatio: undefined,
52
62
  }
53
63
  },
54
- extends: BaseContentBlock,
55
64
  beforeMount() {
56
65
  if (_.isEmpty(this.block.metadata.config)) {
57
66
  this.block.metadata.config = {}
@@ -59,15 +68,13 @@ export default {
59
68
  if (_.isEmpty(this.block.metadata.config.alt)) {
60
69
  this.block.metadata.config.alt = ''
61
70
  }
71
+ if (!_.isBoolean(this.block.metadata.config.hide_background)) {
72
+ this.block.metadata.config.hide_background = false
73
+ }
62
74
  if (_.isEmpty(this.block.metadata.config.aria_describedby)) {
63
75
  this.block.metadata.config.aria_describedby = ''
64
76
  }
65
77
  },
66
- data() {
67
- return {
68
- id: 'image_' + Crypto.id(),
69
- }
70
- },
71
78
  computed: {
72
79
  describedById() {
73
80
  // If there's a described by
@@ -80,6 +87,14 @@ export default {
80
87
  describedByText() {
81
88
  return _.get(this.block.metadata, 'config.aria_describedby', null)
82
89
  },
90
+ imageClass() {
91
+ let imageClass = ''
92
+ // If NOT hide background, inclide the extra class
93
+ if (!_.get(this.block.metadata, 'config.hide_background', false)) {
94
+ imageClass += ' img-white'
95
+ }
96
+ return 'img-display' + imageClass
97
+ },
83
98
  },
84
99
  watch: {
85
100
  value(newValue) {
@@ -108,6 +123,13 @@ export default {
108
123
  .img-holder {
109
124
  max-height: 300px;
110
125
  }
126
+ .img-white {
127
+ background: #fff;
128
+ }
129
+ .no-source-overlay {
130
+ text-align: center;
131
+ margin-top: -175px;
132
+ }
111
133
  ::v-deep .v-skeleton-loader.v-skeleton-loader--is-loading {
112
134
  .v-skeleton-loader__image {
113
135
  height: 100%;
@@ -0,0 +1,159 @@
1
+ <template>
2
+ <div>
3
+ <div v-if="stateLoaded">
4
+ <div v-if="block.body && !submitted">
5
+ <TextViewer v-model="block.body" :height="200"></TextViewer>
6
+ <TextEditor
7
+ v-model="response"
8
+ :height="200"
9
+ menubar=""
10
+ ></TextEditor>
11
+ <p class="pa-3 text-center blue-grey lighten-5">
12
+ <v-btn
13
+ color="primary"
14
+ :disabled="!canSubmit"
15
+ @click="onSubmit"
16
+ >
17
+ {{ $t('shared.forms.submit') }}
18
+ </v-btn>
19
+ </p>
20
+ </div>
21
+
22
+ <div v-else-if="block.body && submitted">
23
+ <TextViewer v-model="block.body" :height="200"></TextViewer>
24
+ <p>
25
+ {{
26
+ $t(
27
+ 'windward.core.components.content.blocks.open_response.your_response'
28
+ )
29
+ }}
30
+ </p>
31
+ <v-alert color="light-blue lighten-4">
32
+ <TextViewer v-model="response" :height="200"></TextViewer>
33
+ </v-alert>
34
+ <div v-if="block.metadata.config.sample_response">
35
+ <p>
36
+ {{
37
+ $t(
38
+ 'windward.core.components.content.blocks.open_response.sample_response'
39
+ )
40
+ }}
41
+ </p>
42
+ <v-alert color="light-blue lighten-4">
43
+ <TextViewer
44
+ v-model="block.metadata.config.sample_response"
45
+ :height="200"
46
+ ></TextViewer>
47
+ </v-alert>
48
+ </div>
49
+ <p class="pa-3 text-center blue-grey lighten-5">
50
+ <v-btn color="primary" @click="submitted = false">{{
51
+ $t('shared.forms.edit')
52
+ }}</v-btn>
53
+ </p>
54
+ </div>
55
+
56
+ <v-alert v-else type="warning">
57
+ {{
58
+ $t(
59
+ 'windward.core.components.content.blocks.open_response.initial_setup'
60
+ )
61
+ }}
62
+ </v-alert>
63
+ </div>
64
+ <div v-if="!stateLoaded">
65
+ <v-progress-circular
66
+ indeterminate
67
+ :size="64"
68
+ :width="4"
69
+ color="white"
70
+ >
71
+ </v-progress-circular>
72
+ </div>
73
+ </div>
74
+ </template>
75
+
76
+ <script>
77
+ import _ from 'lodash'
78
+ import { mapGetters } from 'vuex'
79
+ import TextViewer from '~/components/Text/TextViewer.vue'
80
+ import TextEditor from '~/components/Text/TextEditor.vue'
81
+ import BaseContentBlock from '~/components/Content/Blocks/BaseContentBlock'
82
+ import UserContentBlockState from '~/models/UserContentBlockState'
83
+
84
+ export default {
85
+ name: 'ContentBlockOpenResponse',
86
+ extends: BaseContentBlock,
87
+ components: {
88
+ TextViewer,
89
+ TextEditor,
90
+ },
91
+ data() {
92
+ return {
93
+ stateLoaded: false,
94
+ response: '',
95
+ submitted: false,
96
+ }
97
+ },
98
+ computed: {
99
+ ...mapGetters({
100
+ enrollment: 'enrollment/get',
101
+ }),
102
+ canSubmit() {
103
+ // Make sure the response is not empty and not equal to the starting text
104
+ return (
105
+ this.response &&
106
+ this.response !== this.block.metadata.config.starting_text
107
+ )
108
+ },
109
+ },
110
+ beforeMount() {
111
+ if (_.isEmpty(this.block.body)) {
112
+ this.block.body = ''
113
+ }
114
+ if (_.isEmpty(this.block.metadata.config)) {
115
+ this.block.metadata.config = {}
116
+ }
117
+ if (_.isEmpty(this.block.metadata.config.sample_response)) {
118
+ this.block.metadata.config.sample_response = ''
119
+ }
120
+ if (_.isEmpty(this.block.metadata.config.starting_text)) {
121
+ this.block.metadata.config.starting_text = ''
122
+ }
123
+ },
124
+ watch: {},
125
+ mounted() {},
126
+ methods: {
127
+ async onAfterSetContentBlockState() {
128
+ // Check to see if we have a state already for this block with the same block_id
129
+ // States are loaded via the ContentBlock.id but in this particular case we want to
130
+ // maintain the state ACROSS different ContentBlock.ids but with the same linked Block.id
131
+ const userState = await UserContentBlockState.where({
132
+ 'metadata->block->tag': 'plugin-core-open-response',
133
+ course_user_id: this.enrollment.id,
134
+ })
135
+ .where('metadata->block->block_id', this.block.block_id)
136
+ .first()
137
+
138
+ // Apply the "True" state
139
+ if (!_.isEmpty(userState)) {
140
+ this.response = _.get(userState, 'metadata.response', '')
141
+ this.submitted = _.get(userState, 'metadata.submitted', false)
142
+ }
143
+
144
+ // If after the state is applied the response is still empty then apply the default response
145
+ if (this.response === '') {
146
+ this.response = this.block.metadata.config.starting_text
147
+ }
148
+
149
+ this.stateLoaded = true
150
+ },
151
+ onSubmit() {
152
+ this.submitted = true
153
+
154
+ // Force the state to save on submit and not wait
155
+ this.$Tracking.flushState()
156
+ },
157
+ },
158
+ }
159
+ </script>
@@ -0,0 +1,185 @@
1
+ <template>
2
+ <div>
3
+ <div v-if="block.metadata.config.linked.length">
4
+ <v-btn color="primary" block @click="onCollate">
5
+ <v-icon class="mr-3">mdi-file-word</v-icon>
6
+ {{
7
+ $t(
8
+ 'windward.core.components.content.blocks.open_response_collate.download_document'
9
+ )
10
+ }}
11
+ </v-btn>
12
+ </div>
13
+ <v-alert v-else type="warning">
14
+ {{
15
+ $t(
16
+ 'windward.core.components.content.blocks.open_response_collate.initial_setup'
17
+ )
18
+ }}
19
+ </v-alert>
20
+ </div>
21
+ </template>
22
+
23
+ <script>
24
+ import _ from 'lodash'
25
+ import { mapGetters } from 'vuex'
26
+ import BaseContentBlock from '~/components/Content/Blocks/BaseContentBlock'
27
+ import UserContentBlockState from '~/models/UserContentBlockState'
28
+
29
+ export default {
30
+ name: 'ContentBlockOpenResponseCollate',
31
+ extends: BaseContentBlock,
32
+ components: {},
33
+ data() {
34
+ return {
35
+ saveState: false, // Override the base block to disable state saving
36
+ }
37
+ },
38
+ beforeMount() {
39
+ if (_.isEmpty(this.block.body)) {
40
+ this.block.body = ''
41
+ }
42
+ if (_.isEmpty(this.block.metadata.config)) {
43
+ this.block.metadata.config = {}
44
+ }
45
+ if (_.isEmpty(this.block.metadata.config.linked)) {
46
+ this.block.metadata.config.linked = []
47
+ }
48
+ if (_.isEmpty(this.block.metadata.config.filename)) {
49
+ this.block.metadata.config.filename = ''
50
+ }
51
+ // _.isEmpty(true) returns false. use isBoolean to check if this prop exists
52
+ if (!_.isBoolean(this.block.metadata.config.include_prompts)) {
53
+ this.block.metadata.config.include_prompts = false
54
+ }
55
+ },
56
+ computed: {
57
+ ...mapGetters({
58
+ organization: 'organization/get',
59
+ course: 'course/get',
60
+ enrollment: 'enrollment/get',
61
+ content: 'content/get',
62
+ }),
63
+ },
64
+ watch: {},
65
+ mounted() {},
66
+ methods: {
67
+ async onCollate() {
68
+ try {
69
+ let userState = await UserContentBlockState.where({
70
+ 'metadata->block->tag': 'plugin-core-open-response',
71
+ course_user_id: this.enrollment.id,
72
+ })
73
+ .whereIn(
74
+ 'metadata->block->block_id',
75
+ this.block.metadata.config.linked
76
+ )
77
+ .get()
78
+ let collated = ''
79
+ const sortedStates = []
80
+
81
+ // Sorted the states based on the linked order
82
+ this.block.metadata.config.linked.forEach((linkedId) => {
83
+ const found = userState.find((state) => {
84
+ return state.metadata.block.block_id === linkedId
85
+ })
86
+ if (found) {
87
+ sortedStates.push(found)
88
+ }
89
+ })
90
+
91
+ sortedStates.forEach((state) => {
92
+ // Prepend the prompt from the state if include prompts is enabled
93
+ if (this.block.metadata.config.include_prompts) {
94
+ collated +=
95
+ '<strong>' +
96
+ state.metadata.block.body +
97
+ '</strong><hr />'
98
+ }
99
+ if (!_.isEmpty(state.metadata.response)) {
100
+ collated += '\n' + state.metadata.response
101
+ } else {
102
+ collated +=
103
+ '\n<p>' +
104
+ this.$t(
105
+ 'windward.core.components.content.blocks.open_response_collate.no_response'
106
+ ) +
107
+ '</p>'
108
+ }
109
+ })
110
+ let filename = this.block.metadata.config.filename
111
+ if (_.isEmpty(this.block.metadata.config.filename)) {
112
+ // Default filename is the users name + the current page
113
+ filename =
114
+ this.$auth.user.last_name +
115
+ '_' +
116
+ this.$auth.user.first_name +
117
+ '_' +
118
+ _.get(this.content, 'content.name_prefix') +
119
+ _.get(this.content, 'content.name')
120
+
121
+ // Change spaces to underscores and remove special characters
122
+ filename = filename.replaceAll(/\s+/gi, '_')
123
+ filename = filename.replaceAll(/[^a-z0-9\-\_]/gi, '')
124
+ }
125
+
126
+ this.generateDocument(collated, filename)
127
+ } catch (e) {
128
+ // eslint-disable-next-line no-console
129
+ console.error(e)
130
+ this.$dialog.error(
131
+ this.$t(
132
+ 'windward.core.components.content.blocks.open_response_collate.generate_error'
133
+ )
134
+ )
135
+ }
136
+ },
137
+ generateDocument(htmlBody, filename = '') {
138
+ // Specify file name. If one isn't supplied then a default name of `exported_document_YYYY-MM-DD.doc` is used
139
+ filename = filename
140
+ ? filename + '.doc'
141
+ : 'exported_document_' +
142
+ new Date().toISOString().split('T')[0] +
143
+ '.doc'
144
+
145
+ var preHtml =
146
+ "<html xmlns:o='urn:schemas-microsoft-com:office:office' xmlns:w='urn:schemas-microsoft-com:office:word' xmlns='http://www.w3.org/TR/REC-html40'>" +
147
+ "<head><meta charset='utf-8'><title>" +
148
+ filename +
149
+ '</title></head>' +
150
+ '<body>'
151
+ var postHtml = '</body></html>'
152
+ var html = preHtml + htmlBody + postHtml
153
+
154
+ var blob = new Blob(['\ufeff', html], {
155
+ type: 'application/msword',
156
+ })
157
+
158
+ // Specify link url
159
+ var url =
160
+ 'data:application/vnd.ms-word;charset=utf-8,' +
161
+ encodeURIComponent(html)
162
+
163
+ // Create download link element
164
+ var downloadLink = document.createElement('a')
165
+
166
+ document.body.appendChild(downloadLink)
167
+
168
+ if (navigator.msSaveOrOpenBlob) {
169
+ navigator.msSaveOrOpenBlob(blob, filename)
170
+ } else {
171
+ // Create a link to the file
172
+ downloadLink.href = url
173
+
174
+ // Setting the file name
175
+ downloadLink.download = filename
176
+
177
+ //triggering the function
178
+ downloadLink.click()
179
+ }
180
+
181
+ document.body.removeChild(downloadLink)
182
+ },
183
+ },
184
+ }
185
+ </script>
@@ -17,6 +17,13 @@
17
17
  </template>
18
18
  </ContentBlockAsset>
19
19
 
20
+ <v-switch
21
+ v-model="block.metadata.config.hide_background"
22
+ :label="
23
+ $t('windward.core.components.settings.image.hide_background')
24
+ "
25
+ ></v-switch>
26
+
20
27
  <v-form>
21
28
  <v-text-field
22
29
  v-model="block.metadata.config.alt"
@@ -69,6 +76,9 @@ export default {
69
76
  if (_.isEmpty(this.block.metadata.config.alt)) {
70
77
  this.block.metadata.config.alt = ''
71
78
  }
79
+ if (!_.isBoolean(this.block.metadata.config.hide_background)) {
80
+ this.block.metadata.config.hide_background = false
81
+ }
72
82
  if (_.isEmpty(this.block.metadata.config.aria_describedby)) {
73
83
  this.block.metadata.config.aria_describedby = ''
74
84
  }