@windward/integrations 0.20.0 → 0.23.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 (151) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/components/Content/Blocks/ActionPanel/TransformActivity.vue +386 -0
  3. package/components/Content/Blocks/ActionPanel/TransformBlock.vue +875 -105
  4. package/components/Content/Blocks/ExternalIntegration/LtiConsumer.vue +22 -2
  5. package/components/ExternalIntegration/Driver/Lti1p1/ManageConsumer.vue +8 -2
  6. package/components/ExternalIntegration/Driver/Lti1p1/ManageProvider.vue +4 -0
  7. package/components/ExternalIntegration/Driver/Lti1p3/ManageConsumer.vue +2 -2
  8. package/components/Integration/JobTable.vue +35 -3
  9. package/components/Integration/TranslateCourse.vue +574 -0
  10. package/components/Settings/ExternalIntegration/LtiConsumerSettings.vue +45 -12
  11. package/helpers/ExternalIntegration/ScormHelper.ts +1 -1
  12. package/i18n/ar-SA/components/ai_agent/chat.ts +20 -0
  13. package/i18n/ar-SA/components/ai_agent/index.ts +5 -0
  14. package/i18n/ar-SA/components/content/blocks/action_panel/index.ts +5 -0
  15. package/i18n/ar-SA/components/content/blocks/action_panel/transform_block.ts +9 -0
  16. package/i18n/ar-SA/components/content/blocks/external_integration/index.ts +5 -0
  17. package/i18n/ar-SA/components/content/blocks/external_integration/lti_consumer.ts +17 -0
  18. package/i18n/ar-SA/components/content/blocks/index.ts +7 -0
  19. package/i18n/ar-SA/components/content/index.ts +5 -0
  20. package/i18n/ar-SA/components/external_integration/driver/lti1p1.ts +17 -0
  21. package/i18n/ar-SA/components/external_integration/driver/lti1p3.ts +25 -0
  22. package/i18n/ar-SA/components/external_integration/driver/scorm.ts +14 -0
  23. package/i18n/ar-SA/components/external_integration/index.ts +36 -0
  24. package/i18n/ar-SA/components/external_integration/provider_target.ts +9 -0
  25. package/i18n/ar-SA/components/file_import/index.ts +5 -0
  26. package/i18n/ar-SA/components/file_import/resourcespace.ts +4 -0
  27. package/i18n/ar-SA/components/index.ts +19 -0
  28. package/i18n/ar-SA/components/integration/driver.ts +67 -0
  29. package/i18n/ar-SA/components/integration/index.ts +9 -0
  30. package/i18n/ar-SA/components/integration/job.ts +25 -0
  31. package/i18n/ar-SA/components/integration/job_log.ts +24 -0
  32. package/i18n/ar-SA/components/llm/blooms.ts +15 -0
  33. package/i18n/ar-SA/components/llm/content_selector.ts +3 -0
  34. package/i18n/ar-SA/components/llm/generate_content/fake_text_stream.ts +62 -0
  35. package/i18n/ar-SA/components/llm/generate_content/generate_questions.ts +92 -0
  36. package/i18n/ar-SA/components/llm/generate_content/index.ts +8 -0
  37. package/i18n/ar-SA/components/llm/index.ts +10 -0
  38. package/i18n/ar-SA/components/navigation/index.ts +5 -0
  39. package/i18n/ar-SA/components/navigation/integrations.ts +9 -0
  40. package/i18n/ar-SA/components/settings/external_integration/index.ts +5 -0
  41. package/i18n/ar-SA/components/settings/external_integration/lti_consumer.ts +10 -0
  42. package/i18n/ar-SA/components/settings/index.ts +5 -0
  43. package/i18n/ar-SA/index.ts +16 -0
  44. package/i18n/ar-SA/modules/index.ts +5 -0
  45. package/i18n/ar-SA/pages/admin/index.ts +5 -0
  46. package/i18n/ar-SA/pages/admin/translateCourse.ts +68 -0
  47. package/i18n/ar-SA/pages/course/external_integration/index.ts +6 -0
  48. package/i18n/ar-SA/pages/course/index.ts +5 -0
  49. package/i18n/ar-SA/pages/importContent.ts +3 -0
  50. package/i18n/ar-SA/pages/importCourse.ts +13 -0
  51. package/i18n/ar-SA/pages/index.ts +15 -0
  52. package/i18n/ar-SA/pages/login/index.ts +9 -0
  53. package/i18n/ar-SA/pages/login/lti.ts +23 -0
  54. package/i18n/ar-SA/pages/login/saml.ts +7 -0
  55. package/i18n/ar-SA/pages/login/scorm.ts +28 -0
  56. package/i18n/ar-SA/pages/vendor.ts +11 -0
  57. package/i18n/ar-SA/shared/content_blocks.ts +9 -0
  58. package/i18n/ar-SA/shared/error.ts +9 -0
  59. package/i18n/ar-SA/shared/file.ts +5 -0
  60. package/i18n/ar-SA/shared/index.ts +17 -0
  61. package/i18n/ar-SA/shared/menu.ts +3 -0
  62. package/i18n/ar-SA/shared/notification.ts +14 -0
  63. package/i18n/ar-SA/shared/permission.ts +52 -0
  64. package/i18n/ar-SA/shared/settings.ts +9 -0
  65. package/i18n/en-US/components/content/blocks/action_panel/index.ts +2 -0
  66. package/i18n/en-US/components/content/blocks/action_panel/transform_activity.ts +8 -0
  67. package/i18n/en-US/components/content/blocks/action_panel/transform_block.ts +3 -1
  68. package/i18n/en-US/components/content/blocks/external_integration/lti_consumer.ts +3 -2
  69. package/i18n/en-US/components/integration/job.ts +2 -0
  70. package/i18n/en-US/components/navigation/integrations.ts +1 -0
  71. package/i18n/en-US/components/settings/external_integration/lti_consumer.ts +2 -0
  72. package/i18n/en-US/pages/admin/index.ts +5 -0
  73. package/i18n/en-US/pages/admin/translateCourse.ts +68 -0
  74. package/i18n/en-US/pages/index.ts +2 -0
  75. package/i18n/es-ES/components/content/blocks/action_panel/index.ts +2 -0
  76. package/i18n/es-ES/components/content/blocks/action_panel/transform_activity.ts +8 -0
  77. package/i18n/es-ES/components/content/blocks/action_panel/transform_block.ts +3 -1
  78. package/i18n/es-ES/components/content/blocks/external_integration/lti_consumer.ts +10 -9
  79. package/i18n/es-ES/components/integration/job.ts +2 -0
  80. package/i18n/es-ES/components/navigation/integrations.ts +1 -0
  81. package/i18n/es-ES/components/settings/external_integration/lti_consumer.ts +3 -0
  82. package/i18n/es-ES/pages/admin/index.ts +5 -0
  83. package/i18n/es-ES/pages/admin/translateCourse.ts +68 -0
  84. package/i18n/es-ES/pages/index.ts +2 -0
  85. package/i18n/fr-FR/components/ai_agent/chat.ts +20 -0
  86. package/i18n/fr-FR/components/ai_agent/index.ts +5 -0
  87. package/i18n/fr-FR/components/content/blocks/action_panel/index.ts +5 -0
  88. package/i18n/fr-FR/components/content/blocks/action_panel/transform_block.ts +9 -0
  89. package/i18n/fr-FR/components/content/blocks/external_integration/index.ts +5 -0
  90. package/i18n/fr-FR/components/content/blocks/external_integration/lti_consumer.ts +17 -0
  91. package/i18n/fr-FR/components/content/blocks/index.ts +7 -0
  92. package/i18n/fr-FR/components/content/index.ts +5 -0
  93. package/i18n/fr-FR/components/external_integration/driver/lti1p1.ts +17 -0
  94. package/i18n/fr-FR/components/external_integration/driver/lti1p3.ts +25 -0
  95. package/i18n/fr-FR/components/external_integration/driver/scorm.ts +14 -0
  96. package/i18n/fr-FR/components/external_integration/index.ts +36 -0
  97. package/i18n/fr-FR/components/external_integration/provider_target.ts +9 -0
  98. package/i18n/fr-FR/components/file_import/index.ts +5 -0
  99. package/i18n/fr-FR/components/file_import/resourcespace.ts +4 -0
  100. package/i18n/fr-FR/components/index.ts +19 -0
  101. package/i18n/fr-FR/components/integration/driver.ts +67 -0
  102. package/i18n/fr-FR/components/integration/index.ts +9 -0
  103. package/i18n/fr-FR/components/integration/job.ts +25 -0
  104. package/i18n/fr-FR/components/integration/job_log.ts +24 -0
  105. package/i18n/fr-FR/components/llm/blooms.ts +15 -0
  106. package/i18n/fr-FR/components/llm/content_selector.ts +3 -0
  107. package/i18n/fr-FR/components/llm/generate_content/fake_text_stream.ts +62 -0
  108. package/i18n/fr-FR/components/llm/generate_content/generate_questions.ts +92 -0
  109. package/i18n/fr-FR/components/llm/generate_content/index.ts +8 -0
  110. package/i18n/fr-FR/components/llm/index.ts +10 -0
  111. package/i18n/fr-FR/components/navigation/index.ts +5 -0
  112. package/i18n/fr-FR/components/navigation/integrations.ts +9 -0
  113. package/i18n/fr-FR/components/settings/external_integration/index.ts +5 -0
  114. package/i18n/fr-FR/components/settings/external_integration/lti_consumer.ts +10 -0
  115. package/i18n/fr-FR/components/settings/index.ts +5 -0
  116. package/i18n/fr-FR/index.ts +16 -0
  117. package/i18n/fr-FR/modules/index.ts +5 -0
  118. package/i18n/fr-FR/pages/admin/index.ts +5 -0
  119. package/i18n/fr-FR/pages/admin/translateCourse.ts +68 -0
  120. package/i18n/fr-FR/pages/course/external_integration/index.ts +6 -0
  121. package/i18n/fr-FR/pages/course/index.ts +5 -0
  122. package/i18n/fr-FR/pages/importContent.ts +3 -0
  123. package/i18n/fr-FR/pages/importCourse.ts +13 -0
  124. package/i18n/fr-FR/pages/index.ts +15 -0
  125. package/i18n/fr-FR/pages/login/index.ts +9 -0
  126. package/i18n/fr-FR/pages/login/lti.ts +23 -0
  127. package/i18n/fr-FR/pages/login/saml.ts +7 -0
  128. package/i18n/fr-FR/pages/login/scorm.ts +28 -0
  129. package/i18n/fr-FR/pages/vendor.ts +11 -0
  130. package/i18n/fr-FR/shared/content_blocks.ts +9 -0
  131. package/i18n/fr-FR/shared/error.ts +9 -0
  132. package/i18n/fr-FR/shared/file.ts +5 -0
  133. package/i18n/fr-FR/shared/index.ts +17 -0
  134. package/i18n/fr-FR/shared/menu.ts +3 -0
  135. package/i18n/fr-FR/shared/notification.ts +14 -0
  136. package/i18n/fr-FR/shared/permission.ts +52 -0
  137. package/i18n/fr-FR/shared/settings.ts +9 -0
  138. package/i18n/index.ts +4 -0
  139. package/i18n/sv-SE/components/content/blocks/action_panel/index.ts +2 -0
  140. package/i18n/sv-SE/components/content/blocks/action_panel/transform_activity.ts +8 -0
  141. package/i18n/sv-SE/components/content/blocks/action_panel/transform_block.ts +3 -1
  142. package/i18n/sv-SE/components/content/blocks/external_integration/lti_consumer.ts +11 -10
  143. package/i18n/sv-SE/components/integration/job.ts +6 -4
  144. package/i18n/sv-SE/components/navigation/integrations.ts +1 -0
  145. package/i18n/sv-SE/components/settings/external_integration/lti_consumer.ts +3 -0
  146. package/i18n/sv-SE/pages/admin/index.ts +5 -0
  147. package/i18n/sv-SE/pages/admin/translateCourse.ts +68 -0
  148. package/i18n/sv-SE/pages/index.ts +2 -0
  149. package/package.json +1 -1
  150. package/pages/admin/translateCourse.vue +81 -0
  151. package/plugin.js +38 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # Changelog
2
2
 
3
+ ## Release [0.23.0] - 2026-02-23
4
+
5
+ * Merged in feature/LE-2217/activity-transform-3 (pull request #133)
6
+ * Merged in feature/LE-2217/activity-transform-2 (pull request #132)
7
+ * Merged in feature/LE-2217/activity-transform (pull request #130)
8
+ * Merged in bugfix/LE-2202-lti-integration-block-not-workin (pull request #125)
9
+ * Merged in feature/LE-2215-clickable-icon-default-settings- (pull request #131)
10
+ * Merged in feature/LE-2208-translate-course (pull request #119)
11
+ * Merge remote-tracking branch 'origin/feature/LE-2208-translate-course' into feature/LE-2208-translate-course
12
+ * Merge remote-tracking branch 'origin/feature/LE-2208-translate-course' into feature/LE-2208-translate-course
13
+
14
+
15
+ ## Release [0.21.0] - 2026-01-12
16
+
17
+ * Merged in feature/LE-221/block-transform-additions (pull request #127)
18
+ * Merged in feature/LE-2218/endless-spinner (pull request #126)
19
+ * Merge branch 'feature/LE-2218/endless-spinner' into feature/LE-221/block-transform-additions
20
+ * Merged in feature/LE-2155-consistent-ui-for-adding-new-blo (pull request #124)
21
+
22
+
3
23
  ## Release [0.20.0] - 2025-12-03
4
24
 
5
25
  * Merged in feature/LE-2177-switch-block-type-for-text-heavy (pull request #118)
@@ -0,0 +1,386 @@
1
+ <template>
2
+ <v-list-item-group v-if="canTransformActivity" :disabled="isTransforming">
3
+ <v-list-group v-model="showMenu" @click="onClickShowTransforms">
4
+ <template #activator>
5
+ <v-list-item-icon>
6
+ <v-progress-circular
7
+ v-if="isTransforming"
8
+ indeterminate
9
+ ></v-progress-circular>
10
+ <v-icon v-if="!isTransforming">mdi-shape</v-icon>
11
+ </v-list-item-icon>
12
+ <v-list-item-title>
13
+ {{
14
+ $t(
15
+ 'windward.integrations.components.content.blocks.action_panel.transform_activity.change_block_type'
16
+ )
17
+ }}
18
+ </v-list-item-title>
19
+ </template>
20
+
21
+ <v-list-item
22
+ v-for="action in availableActions"
23
+ :key="action.tag"
24
+ :disabled="isTransforming"
25
+ @click="performActivityTransform($event, action.tag)"
26
+ >
27
+ <v-list-item-title>
28
+ <v-icon>mdi-arrow-right</v-icon> {{ action.label }}
29
+ </v-list-item-title>
30
+ </v-list-item>
31
+ </v-list-group>
32
+ </v-list-item-group>
33
+ </template>
34
+
35
+ <script>
36
+ import _ from 'lodash'
37
+ import { mapGetters } from 'vuex'
38
+ import Organization from '~/models/Organization'
39
+ import Course from '~/models/Course'
40
+
41
+ const DEFAULT_INSTRUCTIONS_BY_TAG = {
42
+ 'plugin-games-flash-card':
43
+ 'windward.games.components.settings.flashcard.form.instructions',
44
+ 'plugin-games-matching-game':
45
+ 'windward.games.components.settings.matching_game.form.default_instructions',
46
+ 'plugin-games-bucket':
47
+ 'windward.games.components.settings.bucket_game.form.default_instructions',
48
+ 'plugin-games-seven-strikes-game':
49
+ 'windward.games.components.settings.seven_strikes.instructions',
50
+ 'plugin-games-wordjumble-game':
51
+ 'windward.games.components.content.blocks.word_jumble.instructions',
52
+ 'plugin-games-crossword-puzzle-game':
53
+ 'windward.games.components.settings.crossword.instructions',
54
+ 'plugin-games-multiple-choice':
55
+ 'windward.games.components.settings.multiple_choice.default_instructions',
56
+ }
57
+
58
+ const DEFAULT_TITLE_BY_TAG = {
59
+ 'plugin-games-flash-card':
60
+ 'windward.games.components.content.blocks.flashcard.title',
61
+ 'plugin-games-matching-game':
62
+ 'windward.games.components.settings.matching_game.form.title',
63
+ 'plugin-games-bucket':
64
+ 'windward.games.components.content.blocks.bucket_game.game_title',
65
+ 'plugin-games-seven-strikes-game':
66
+ 'windward.games.components.settings.seven_strikes.title',
67
+ 'plugin-games-wordjumble-game':
68
+ 'windward.games.components.settings.word_jumble.title',
69
+ 'plugin-games-crossword-puzzle-game':
70
+ 'windward.games.components.content.blocks.crossword.crossword',
71
+ 'plugin-games-multiple-choice':
72
+ 'windward.games.components.content.blocks.multiple_choice.game_title',
73
+ }
74
+
75
+ const SUPPORTED_ACTIVITY_ACTIONS = [
76
+ {
77
+ tag: 'plugin-games-flash-card',
78
+ labelKey: 'windward.games.shared.content_blocks.title.flashcards',
79
+ },
80
+ {
81
+ tag: 'plugin-games-matching-game',
82
+ labelKey: 'windward.games.shared.content_blocks.title.matching_game',
83
+ },
84
+ {
85
+ tag: 'plugin-games-bucket',
86
+ labelKey: 'windward.games.shared.content_blocks.title.bucket',
87
+ },
88
+ {
89
+ tag: 'plugin-games-seven-strikes-game',
90
+ labelKey: 'windward.games.shared.content_blocks.title.seven_strikes',
91
+ },
92
+ {
93
+ tag: 'plugin-games-wordjumble-game',
94
+ labelKey: 'windward.games.shared.content_blocks.title.word_jumble',
95
+ },
96
+ {
97
+ tag: 'plugin-games-crossword-puzzle-game',
98
+ labelKey: 'windward.games.shared.content_blocks.title.crossword_puzzle',
99
+ },
100
+ {
101
+ tag: 'plugin-games-multiple-choice',
102
+ labelKey: 'windward.games.shared.content_blocks.title.multiple_choice',
103
+ },
104
+ ]
105
+
106
+ export default {
107
+ props: {
108
+ value: { type: Object, required: false, default: null },
109
+ index: { type: Number, required: false, default: 0 },
110
+ length: { type: Number, required: false, default: 0 },
111
+ bindElement: { type: null, required: false, default: null },
112
+ draggable: { type: Boolean, required: false, default: true },
113
+ savable: { type: Boolean, required: false, default: true },
114
+ editable: { type: Boolean, required: false, default: true },
115
+ deletable: { type: Boolean, required: false, default: true },
116
+ editMode: { type: Boolean, required: false, default: null },
117
+ saving: { type: Boolean, required: false, default: null },
118
+ btnGroupId: { type: String, required: false, default: '' },
119
+ },
120
+
121
+ data() {
122
+ return {
123
+ showMenu: false,
124
+ isTransforming: false,
125
+ }
126
+ },
127
+
128
+ computed: {
129
+ ...mapGetters({
130
+ organization: 'organization/get',
131
+ course: 'course/get',
132
+ }),
133
+ sourceTag() {
134
+ return _.get(this.value, 'tag', '')
135
+ },
136
+ isSupportedSource() {
137
+ return SUPPORTED_ACTIVITY_ACTIONS.some(
138
+ (action) => action.tag === this.sourceTag
139
+ )
140
+ },
141
+ availableActions() {
142
+ if (!this.value || !this.isSupportedSource) {
143
+ return []
144
+ }
145
+
146
+ return SUPPORTED_ACTIVITY_ACTIONS.filter(
147
+ (action) => action.tag !== this.sourceTag
148
+ ).map((action) => ({
149
+ tag: action.tag,
150
+ label: this.$t(action.labelKey),
151
+ }))
152
+ },
153
+ canTransformActivity() {
154
+ return this.availableActions.length > 0
155
+ },
156
+ },
157
+
158
+ methods: {
159
+ onClickShowTransforms(e) {
160
+ e.stopPropagation()
161
+ },
162
+ getDefaultInstructions(tag) {
163
+ const key = DEFAULT_INSTRUCTIONS_BY_TAG[tag] || ''
164
+ if (!key) {
165
+ return ''
166
+ }
167
+
168
+ const translated = this.$t(key)
169
+
170
+ if (!translated || translated === key) {
171
+ return ''
172
+ }
173
+
174
+ return translated
175
+ },
176
+ getDefaultTitle(tag) {
177
+ const key = DEFAULT_TITLE_BY_TAG[tag] || ''
178
+ if (!key) {
179
+ return ''
180
+ }
181
+
182
+ const translated = this.$t(key)
183
+
184
+ if (!translated || translated === key) {
185
+ return ''
186
+ }
187
+
188
+ return translated
189
+ },
190
+ buildNewBlockBase(sourceBlock) {
191
+ const baseOrderRaw = _.get(sourceBlock, 'order', 0)
192
+ const baseOrder = Number(baseOrderRaw)
193
+ const normalizedOrder = Number.isFinite(baseOrder)
194
+ ? Math.trunc(baseOrder)
195
+ : 0
196
+
197
+ const newBlock = {
198
+ id: _.uniqueId('create_content_block_'),
199
+ content_id: null,
200
+ tag: '',
201
+ body: '',
202
+ status: 'draft',
203
+ order: normalizedOrder,
204
+ type: {
205
+ save_state: false,
206
+ trackable: false,
207
+ completable: false,
208
+ },
209
+ assets: _.cloneDeep(_.get(sourceBlock, 'assets', [])),
210
+ metadata: {
211
+ config: {},
212
+ },
213
+ }
214
+
215
+ const display = _.cloneDeep(_.get(sourceBlock, 'metadata.display', null))
216
+ if (display) {
217
+ newBlock.metadata.display = display
218
+ }
219
+
220
+ return newBlock
221
+ },
222
+ buildSourceBlockPayload(sourceBlock) {
223
+ return {
224
+ tag: _.get(sourceBlock, 'tag', ''),
225
+ body: _.get(sourceBlock, 'body', ''),
226
+ metadata: _.cloneDeep(_.get(sourceBlock, 'metadata', {})),
227
+ assets: _.cloneDeep(_.get(sourceBlock, 'assets', [])),
228
+ }
229
+ },
230
+ async requestActivityTransform(targetTag) {
231
+ const organizationId = _.get(this.organization, 'id', null)
232
+ const courseId = _.get(this.course, 'id', null)
233
+
234
+ if (!organizationId || !courseId) {
235
+ throw new Error('missing_context')
236
+ }
237
+
238
+ const request = new Course()
239
+ request.custom(
240
+ new Organization({ id: organizationId }),
241
+ new Course({ id: courseId }),
242
+ 'llm-activity-transform'
243
+ )
244
+
245
+ const resourcePath = request._customResource
246
+ if (!resourcePath) {
247
+ throw new Error('missing_resource')
248
+ }
249
+
250
+ const payload = {
251
+ source_block: this.buildSourceBlockPayload(this.value),
252
+ target_tag: targetTag,
253
+ language: this.$i18n.locale,
254
+ }
255
+
256
+ const requestConfig = request._reqConfig(
257
+ {
258
+ method: 'POST',
259
+ url: `${request.baseURL()}/${resourcePath}`,
260
+ data: payload,
261
+ },
262
+ { forceMethod: true }
263
+ )
264
+
265
+ const response = await request.request(requestConfig)
266
+ const responseData = response?.data ?? response
267
+
268
+ const wrapKey = typeof request.wrap === 'function' ? request.wrap() : ''
269
+ const looksLikeBlock = (value) => {
270
+ return (
271
+ value &&
272
+ typeof value === 'object' &&
273
+ !Array.isArray(value) &&
274
+ typeof value.tag === 'string' &&
275
+ value.metadata &&
276
+ typeof value.metadata === 'object'
277
+ )
278
+ }
279
+
280
+ let parsed = responseData
281
+
282
+ // Handle Laravel JsonResource wrapping (and occasional double-wrapping)
283
+ for (let i = 0; i < 2; i++) {
284
+ if (looksLikeBlock(parsed)) {
285
+ break
286
+ }
287
+
288
+ if (
289
+ parsed &&
290
+ typeof parsed === 'object' &&
291
+ !Array.isArray(parsed) &&
292
+ wrapKey &&
293
+ Object.prototype.hasOwnProperty.call(parsed, wrapKey)
294
+ ) {
295
+ parsed = parsed[wrapKey]
296
+ continue
297
+ }
298
+
299
+ break
300
+ }
301
+
302
+ return parsed
303
+ },
304
+ async performActivityTransform(e, targetTag) {
305
+ e.stopPropagation()
306
+
307
+ if (this.isTransforming) {
308
+ return
309
+ }
310
+
311
+ if (!this.value || !this.isSupportedSource) {
312
+ return
313
+ }
314
+
315
+ this.isTransforming = true
316
+
317
+ let transformed = null
318
+
319
+ try {
320
+ transformed = await this.requestActivityTransform(targetTag)
321
+
322
+ if (
323
+ !transformed ||
324
+ typeof transformed.tag !== 'string' ||
325
+ !transformed.metadata ||
326
+ typeof transformed.metadata !== 'object'
327
+ ) {
328
+ throw new Error('invalid_response')
329
+ }
330
+
331
+ const newBlock = this.buildNewBlockBase(this.value)
332
+ newBlock.tag = transformed.tag
333
+ newBlock.body = transformed.body || ''
334
+ newBlock.metadata = _.merge(
335
+ {},
336
+ newBlock.metadata,
337
+ _.cloneDeep(transformed.metadata)
338
+ )
339
+ _.set(
340
+ newBlock,
341
+ 'metadata.config.instructions',
342
+ this.getDefaultInstructions(targetTag)
343
+ )
344
+ _.set(
345
+ newBlock,
346
+ 'metadata.config.title',
347
+ this.getDefaultTitle(targetTag)
348
+ )
349
+
350
+ this.$eb.$emit('create:content-block', newBlock)
351
+
352
+ const activeBlock = _.cloneDeep(newBlock)
353
+ this.$ContentService.setContentBlock(activeBlock)
354
+ this.$eb.$emit('block:focus', activeBlock)
355
+ } catch (error) {
356
+ // eslint-disable-next-line no-console
357
+ console.error('Activity transform failed', error)
358
+ if (process.env.NODE_ENV !== 'production') {
359
+ // eslint-disable-next-line no-console
360
+ console.error('Activity transform response payload', transformed)
361
+ }
362
+
363
+ const messageKey = _.get(error, 'response.data.error.message', '')
364
+
365
+ if (this.$toast) {
366
+ if (messageKey === 'activity_transform.error.content_mismatch') {
367
+ this.$toast.error(
368
+ this.$t(
369
+ 'windward.integrations.components.content.blocks.action_panel.transform_activity.change_block_type_insufficient_items'
370
+ )
371
+ )
372
+ } else {
373
+ this.$toast.error(
374
+ this.$t(
375
+ 'windward.integrations.components.content.blocks.action_panel.transform_activity.change_block_type_error'
376
+ )
377
+ )
378
+ }
379
+ }
380
+ } finally {
381
+ this.isTransforming = false
382
+ }
383
+ },
384
+ },
385
+ }
386
+ </script>