@windward/core 0.25.0 → 0.26.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # Changelog
2
2
 
3
+ ## Release [0.26.0] - 2025-12-05
4
+
5
+ * Merged in feature/LE-2154-open-response-download-add-a-tit (pull request #461)
6
+ * Merged in feature/LE-2156-block-settings-label (pull request #458)
7
+ * Merged in LE-2124-move-some-blocks-to-activities-s (pull request #459)
8
+ * Merged in bugfix/LE-2205-open-response-field-rendering-sw (pull request #460)
9
+ * Merged release/0.26.0 into bugfix/LE-2205-open-response-field-rendering-sw
10
+ * hotfix: add starting text support for OpenResponse blocks and enhance content insertion logic in TinyMCE
11
+ * Merged in hotfix/0.25.1 (pull request #456)
12
+ * Merged in feature/LE-2108/revise-text-fix (pull request #453)
13
+ * Merged in feature/LE-2123/open-res-gen-fix (pull request #452)
14
+ * Merged in release/0.25.0 (pull request #448)
15
+ * Merged in release/0.24.0 (pull request #442)
16
+
17
+
18
+ ## Hotfix [0.25.1] - 2025-11-07
19
+
20
+ * Merged in feature/LE-2108/revise-text-fix (pull request #453)
21
+ * Merged in feature/LE-2123/open-res-gen-fix (pull request #452)
22
+
23
+
3
24
  ## Release [0.25.0] - 2025-10-29
4
25
 
5
26
  * Merged in bugfix/LE-2067-scorm-provider (pull request #451)
@@ -3,7 +3,8 @@
3
3
  <v-container
4
4
  v-if="
5
5
  block.metadata.config.title ||
6
- block.metadata.config.instructions
6
+ block.metadata.config.instructions ||
7
+ block.metadata.config.starting_text
7
8
  "
8
9
  class="pa-0"
9
10
  >
@@ -1,5 +1,32 @@
1
1
  <template>
2
2
  <div>
3
+ <div>
4
+ <v-container
5
+ v-if="
6
+ block.metadata.config.title ||
7
+ block.metadata.config.instructions
8
+ "
9
+ class="pa-0"
10
+ >
11
+ <h2
12
+ v-if="
13
+ block.metadata.config.title &&
14
+ block.metadata.config.display_title
15
+ "
16
+ tabindex="0"
17
+ >
18
+ {{ block.metadata.config.title }}
19
+ </h2>
20
+
21
+ <p
22
+ v-if="block.metadata.config.instructions"
23
+ tabindex="0"
24
+ class="pt-3"
25
+ >
26
+ {{ block.metadata.config.instructions }}
27
+ </p>
28
+ </v-container>
29
+ </div>
3
30
  <div v-if="block.metadata.config.linked.length">
4
31
  <v-btn
5
32
  elevation="0"
@@ -1,6 +1,10 @@
1
1
  <template>
2
2
  <v-container>
3
3
  <v-form>
4
+ <BaseContentBlockSettings
5
+ v-model="block.metadata.config"
6
+ :disabled="render"
7
+ ></BaseContentBlockSettings>
4
8
  <p>
5
9
  {{
6
10
  $t(
@@ -95,10 +99,11 @@ import BaseContentSettings from '~/components/Content/Settings/BaseContentSettin
95
99
  import ContentBlock from '~/models/ContentBlock'
96
100
  import Course from '~/models/Course'
97
101
  import TextEditor from '~/components/Text/TextEditor'
102
+ import BaseContentBlockSettings from '~/components/Content/Settings/BaseContentBlockSettings.vue'
98
103
 
99
104
  export default {
100
105
  name: 'OpenResponseCollateSettings',
101
- components: { TextEditor },
106
+ components: { TextEditor, BaseContentBlockSettings },
102
107
  extends: BaseContentSettings,
103
108
  props: {
104
109
  settings: { type: Object, required: false, default: null },
@@ -152,6 +157,9 @@ export default {
152
157
  if (_.isEmpty(this.block.metadata.config.filename)) {
153
158
  this.block.metadata.config.filename = ''
154
159
  }
160
+ if (!_.isBoolean(this.block.metadata.config.display_title)) {
161
+ this.$set(this.block.metadata.config, 'display_title', true)
162
+ }
155
163
  if (_.isEmpty(this.block.metadata.config.additional_text)) {
156
164
  this.block.metadata.config.additional_text = ''
157
165
  }
@@ -610,6 +610,26 @@ export default {
610
610
  return
611
611
  }
612
612
 
613
+ const findBlockAncestor = (node) => {
614
+ try {
615
+ if (!node) return null
616
+ const body = editor ? editor.getBody() : null
617
+ let current = node
618
+ const isBlock = (n) => {
619
+ if (!n || n.nodeType !== Node.ELEMENT_NODE) return false
620
+ const name = n.nodeName || ''
621
+ return /^(P|DIV|LI|UL|OL|H1|H2|H3|H4|H5|H6)$/.test(name)
622
+ }
623
+ while (current && current !== body) {
624
+ if (isBlock(current)) return current
625
+ current = current.parentNode
626
+ }
627
+ return null
628
+ } catch (_e) {
629
+ return null
630
+ }
631
+ }
632
+
613
633
  if (useSelection) {
614
634
  const range = selection.getRng()
615
635
  if (
@@ -703,43 +723,83 @@ export default {
703
723
 
704
724
  editor.undoManager.transact(() => {
705
725
  if (useSelection) {
706
- const range = selection.getRng()
707
- const fragment = editor.dom.createFragment(
708
- responseData.html
709
- )
710
-
711
- if (!fragment.hasChildNodes()) {
712
- return
713
- }
714
-
715
- const firstNode = fragment.firstChild
716
- const lastNode = fragment.lastChild
717
-
718
- if (!firstNode || !lastNode) {
719
- return
720
- }
721
-
722
- range.deleteContents()
723
- range.insertNode(fragment)
724
-
725
- const newRange = editor.dom.createRng()
726
+ try {
727
+ const rng = selection.getRng()
728
+ const startBlock = findBlockAncestor(
729
+ rng ? rng.startContainer : null
730
+ )
731
+ const endBlock = findBlockAncestor(
732
+ rng ? rng.endContainer : null
733
+ )
726
734
 
727
- if (firstNode.nodeType === Node.TEXT_NODE) {
728
- newRange.setStart(firstNode, 0)
729
- } else {
730
- newRange.setStartBefore(firstNode)
735
+ // If selection spans multiple block elements, expand to full blocks
736
+ if (
737
+ startBlock &&
738
+ endBlock &&
739
+ startBlock !== endBlock
740
+ ) {
741
+ const expanded = editor.dom.createRng()
742
+ expanded.setStartBefore(startBlock)
743
+ expanded.setEndAfter(endBlock)
744
+ editor.selection.setRng(expanded)
745
+ }
746
+ } catch (_e) {
747
+ // If expansion fails, fall back to current selection
731
748
  }
732
749
 
733
- if (lastNode.nodeType === Node.TEXT_NODE) {
734
- newRange.setEnd(
735
- lastNode,
736
- lastNode.textContent ? lastNode.textContent.length : 0
737
- )
738
- } else {
739
- newRange.setEndAfter(lastNode)
750
+ // Wrap response with temporary markers so we can reselect inserted content
751
+ const startId = `ww-revise-start-${this.seed}-${Date.now()}-${Math.random()
752
+ .toString(36)
753
+ .slice(2)}`
754
+ const endId = `ww-revise-end-${this.seed}-${Date.now()}-${Math.random()
755
+ .toString(36)
756
+ .slice(2)}`
757
+ const wrappedHtml =
758
+ `<span id="${startId}" data-ww-revise="s"></span>` +
759
+ responseData.html +
760
+ `<span id="${endId}" data-ww-revise="e"></span>`
761
+
762
+ editor.selection.setContent(wrappedHtml)
763
+
764
+ // Try to reselect the inserted content and remove markers
765
+ try {
766
+ const doc = editor.getDoc()
767
+ const startEl = doc.getElementById(startId)
768
+ const endEl = doc.getElementById(endId)
769
+ if (startEl && endEl) {
770
+ const selectRange = editor.dom.createRng()
771
+ // Select everything between markers
772
+ if (selectRange.setStartAfter && selectRange.setEndBefore) {
773
+ selectRange.setStartAfter(startEl)
774
+ selectRange.setEndBefore(endEl)
775
+ } else {
776
+ // Fallback to parent/offset if needed
777
+ const startParent = startEl.parentNode
778
+ const endParent = endEl.parentNode
779
+ const childIndex = (node) => {
780
+ let i = 0
781
+ let cur = node
782
+ while (cur && cur.previousSibling) {
783
+ i++
784
+ cur = cur.previousSibling
785
+ }
786
+ return i
787
+ }
788
+ const startIndex = childIndex(startEl) + 1
789
+ const endIndex = childIndex(endEl)
790
+ selectRange.setStart(startParent, startIndex)
791
+ selectRange.setEnd(endParent, endIndex)
792
+ }
793
+ editor.selection.setRng(selectRange)
794
+
795
+ // Remove markers after selection is set
796
+ if (startEl.parentNode) startEl.parentNode.removeChild(startEl)
797
+ if (endEl.parentNode) endEl.parentNode.removeChild(endEl)
798
+
799
+ }
800
+ } catch (_e) {
801
+ // Ignore selection restoration errors
740
802
  }
741
-
742
- editor.selection.setRng(newRange)
743
803
  } else {
744
804
  editor.setContent(responseData.html)
745
805
  }
@@ -1,24 +1,7 @@
1
1
  export default {
2
2
  title: {
3
- assessment: 'Assessment Settings',
4
- open_response: 'Open Response Settings',
5
- open_response_collate: 'Open Response Download Settings',
6
- image: 'Image Settings',
7
- user_upload: 'User Upload Settings',
8
- file_download: 'File Download Settings',
9
- tab_settings: 'Tab Settings',
10
- text_editor: 'Text Editor Settings',
11
- clickable_icons: 'Clickable Icons Settings',
12
- scenario_choice: 'Scenario Choice',
13
- accordion: 'Accordion Settings',
14
- video: 'Video / Audio Settings',
15
- table: 'Table Settings',
16
- math: 'Math Settings',
17
- feedback: 'Feedback Settings',
18
- horizontal_line: 'Divider Settings',
19
- email: 'Email Settings',
3
+ block_builder: 'Block Builder',
20
4
  click_to_enter: 'Click here to enter text',
21
- block_quote: 'Block Quote Settings',
22
5
  },
23
6
  errors: {
24
7
  input_limitations: 'Must be less than {0} characters.',
@@ -1,25 +1,7 @@
1
1
  export default {
2
2
  title: {
3
- assessment: 'Configuración de evaluación',
4
- open_response: 'Abrir configuración de respuesta',
5
- open_response_collate: 'Abrir configuración de descarga de respuesta',
6
- image: 'Configuración de imagen',
7
- user_upload: 'Configuración de carga del usuario',
8
- file_download: 'Configuración de descarga de archivos',
9
- tab_settings: 'Configuración de pestaña',
10
- text_editor: 'Configuración del editor de texto',
11
- clickable_icons:
12
- 'Configuración de iconos en los que se puede hacer clic',
13
- scenario_choice: 'Elección de escenario',
14
- accordion: 'Configuración de acordeón',
15
- video: 'Configuración de video/audio',
16
- table: 'Configuración de la tabla',
17
- math: 'Configuración matemática',
18
- feedback: 'Configuración de comentarios',
19
- horizontal_line: 'Configuración del divisor',
20
- email: 'Ajustes del correo electrónico',
3
+ block_builder: 'Constructor de bloques',
21
4
  click_to_enter: 'Haga clic para ingresar texto',
22
- block_quote: 'Configuración de cotización en bloque',
23
5
  },
24
6
  errors: {
25
7
  input_limitations: 'Debe tener menos de {0} caracteres.',
@@ -1,24 +1,7 @@
1
1
  export default {
2
2
  title: {
3
- assessment: 'Bedömningsinställningar',
4
- open_response: 'Öppna svarsinställningar',
5
- open_response_collate: 'Öppna inställningar för nedladdning av svar',
6
- image: 'Bildinställningar',
7
- user_upload: 'Användaruppladdningsinställningar',
8
- file_download: 'Filnedladdningsinställningar',
9
- tab_settings: 'Flikinställningar',
10
- text_editor: 'Textredigeringsinställningar',
11
- clickable_icons: 'Inställningar för klickbara ikoner',
12
- scenario_choice: 'Scenarioval',
13
- accordion: 'Accordion Settings',
14
- video: 'Video/ljudinställningar',
15
- table: 'Tabellinställningar',
16
- math: 'Matematiska inställningar',
17
- feedback: 'Feedback-inställningar',
18
- horizontal_line: 'Inställningar för avdelare',
19
- email: 'E-postinställningar',
3
+ block_builder: 'Blockbyggare',
20
4
  click_to_enter: 'Klicka för att skriva in text',
21
- block_quote: 'Blockera offertinställningar',
22
5
  },
23
6
  errors: {
24
7
  input_limitations: 'Måste vara mindre än {0} tecken.',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@windward/core",
3
- "version": "0.25.0",
3
+ "version": "0.26.0",
4
4
  "description": "Windward UI Core Plugins",
5
5
  "main": "plugin.js",
6
6
  "scripts": {
package/plugin.js CHANGED
@@ -166,7 +166,7 @@ export default {
166
166
  metadata: {
167
167
  icon: 'mdi-text-long',
168
168
  name: 'windward.core.shared.content_blocks.title.open_response',
169
- grouping: 'components.content.blocks.group.basic',
169
+ grouping: 'components.content.blocks.group.activities',
170
170
  },
171
171
  },
172
172
  {
@@ -175,7 +175,7 @@ export default {
175
175
  metadata: {
176
176
  icon: 'mdi-cloud-download',
177
177
  name: 'windward.core.shared.content_blocks.title.open_response_collate',
178
- grouping: 'components.content.blocks.group.basic',
178
+ grouping: 'components.content.blocks.group.activities',
179
179
  },
180
180
  },
181
181
  {
@@ -220,7 +220,7 @@ export default {
220
220
  metadata: {
221
221
  icon: 'mdi-message',
222
222
  name: 'windward.core.shared.content_blocks.title.feedback',
223
- grouping: 'components.content.blocks.group.basic',
223
+ grouping: 'components.content.blocks.group.activities',
224
224
  },
225
225
  },
226
226
  {
@@ -258,7 +258,7 @@ export default {
258
258
  context: ['block.core-open-response'],
259
259
  metadata: {
260
260
  icon: 'mdi-cog',
261
- name: 'windward.core.shared.settings.title.open_response',
261
+ name: 'windward.core.shared.settings.title.block_builder',
262
262
  },
263
263
  },
264
264
  {
@@ -267,7 +267,7 @@ export default {
267
267
  context: ['block.core-open-response-collate'],
268
268
  metadata: {
269
269
  icon: 'mdi-cog',
270
- name: 'windward.core.shared.settings.title.open_response_collate',
270
+ name: 'windward.core.shared.settings.title.block_builder',
271
271
  },
272
272
  },
273
273
  {
@@ -276,7 +276,7 @@ export default {
276
276
  context: ['block.core-image'],
277
277
  metadata: {
278
278
  icon: 'mdi-cog',
279
- name: 'windward.core.shared.settings.title.image',
279
+ name: 'windward.core.shared.settings.title.block_builder',
280
280
  },
281
281
  },
282
282
  {
@@ -285,7 +285,7 @@ export default {
285
285
  context: ['block.core-user-upload'],
286
286
  metadata: {
287
287
  icon: 'mdi-cog',
288
- name: 'windward.core.shared.settings.title.user_upload',
288
+ name: 'windward.core.shared.settings.title.block_builder',
289
289
  },
290
290
  },
291
291
  {
@@ -294,7 +294,7 @@ export default {
294
294
  context: ['block.core-file-download'],
295
295
  metadata: {
296
296
  icon: 'mdi-cog',
297
- name: 'windward.core.shared.settings.title.file_download',
297
+ name: 'windward.core.shared.settings.title.block_builder',
298
298
  },
299
299
  },
300
300
  {
@@ -303,7 +303,7 @@ export default {
303
303
  context: ['block.core-tab'],
304
304
  metadata: {
305
305
  icon: 'mdi-cog',
306
- name: 'windward.core.shared.settings.title.tab_settings',
306
+ name: 'windward.core.shared.settings.title.block_builder',
307
307
  },
308
308
  },
309
309
  {
@@ -312,7 +312,7 @@ export default {
312
312
  context: ['block.core-clickable-icons'],
313
313
  metadata: {
314
314
  icon: 'mdi-cog',
315
- name: 'windward.core.shared.settings.title.clickable_icons',
315
+ name: 'windward.core.shared.settings.title.block_builder',
316
316
  },
317
317
  },
318
318
  {
@@ -321,7 +321,7 @@ export default {
321
321
  context: ['block.core-scenario-choice'],
322
322
  metadata: {
323
323
  icon: 'mdi-cog',
324
- name: 'windward.core.shared.settings.title.scenario_choice',
324
+ name: 'windward.core.shared.settings.title.block_builder',
325
325
  },
326
326
  },
327
327
  {
@@ -330,7 +330,7 @@ export default {
330
330
  context: ['block.core-video'],
331
331
  metadata: {
332
332
  icon: 'mdi-cog',
333
- name: 'windward.core.shared.settings.title.video',
333
+ name: 'windward.core.shared.settings.title.block_builder',
334
334
  },
335
335
  },
336
336
  {
@@ -339,7 +339,7 @@ export default {
339
339
  context: ['block.core-accordion'],
340
340
  metadata: {
341
341
  icon: 'mdi-cog',
342
- name: 'windward.core.shared.settings.title.accordion',
342
+ name: 'windward.core.shared.settings.title.block_builder',
343
343
  },
344
344
  },
345
345
  {
@@ -348,7 +348,7 @@ export default {
348
348
  context: ['block.core-table'],
349
349
  metadata: {
350
350
  icon: 'mdi-cog',
351
- name: 'windward.core.shared.settings.title.table',
351
+ name: 'windward.core.shared.settings.title.block_builder',
352
352
  },
353
353
  },
354
354
  {
@@ -357,7 +357,7 @@ export default {
357
357
  context: ['block.content-blocks-text'],
358
358
  metadata: {
359
359
  icon: 'mdi-notebook-outline',
360
- name: 'windward.core.shared.settings.title.text_editor',
360
+ name: 'windward.core.shared.settings.title.block_builder',
361
361
  },
362
362
  },
363
363
  {
@@ -366,7 +366,7 @@ export default {
366
366
  context: ['block.core-feedback'],
367
367
  metadata: {
368
368
  icon: 'mdi-notebook-outline',
369
- name: 'windward.core.shared.settings.title.feedback',
369
+ name: 'windward.core.shared.settings.title.block_builder',
370
370
  },
371
371
  },
372
372
  {
@@ -375,7 +375,7 @@ export default {
375
375
  context: ['block.core-email'],
376
376
  metadata: {
377
377
  icon: 'mdi-notebook-outline',
378
- name: 'windward.core.shared.settings.title.email',
378
+ name: 'windward.core.shared.settings.title.block_builder',
379
379
  },
380
380
  },
381
381
  {
@@ -384,7 +384,7 @@ export default {
384
384
  context: ['block.core-block-quote'],
385
385
  metadata: {
386
386
  icon: 'mdi-notebook-outline',
387
- name: 'windward.core.shared.settings.title.block_quote',
387
+ name: 'windward.core.shared.settings.title.block_builder',
388
388
  },
389
389
  },
390
390
  {
@@ -393,7 +393,7 @@ export default {
393
393
  context: ['block.core-horizontal-rule'],
394
394
  metadata: {
395
395
  icon: 'mdi-cog',
396
- name: 'windward.core.shared.settings.title.horizontal_line',
396
+ name: 'windward.core.shared.settings.title.block_builder',
397
397
  },
398
398
  },
399
399
  ],