@windward/integrations 0.21.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.
- package/CHANGELOG.md +12 -0
- package/components/Content/Blocks/ActionPanel/TransformActivity.vue +386 -0
- package/components/Content/Blocks/ActionPanel/TransformBlock.vue +402 -59
- package/components/Content/Blocks/ExternalIntegration/LtiConsumer.vue +22 -2
- package/components/ExternalIntegration/Driver/Lti1p1/ManageConsumer.vue +8 -2
- package/components/ExternalIntegration/Driver/Lti1p1/ManageProvider.vue +4 -0
- package/components/ExternalIntegration/Driver/Lti1p3/ManageConsumer.vue +2 -2
- package/components/Integration/JobTable.vue +35 -3
- package/components/Integration/TranslateCourse.vue +574 -0
- package/components/Settings/ExternalIntegration/LtiConsumerSettings.vue +27 -0
- package/i18n/ar-SA/components/ai_agent/chat.ts +20 -0
- package/i18n/ar-SA/components/ai_agent/index.ts +5 -0
- package/i18n/ar-SA/components/content/blocks/action_panel/index.ts +5 -0
- package/i18n/ar-SA/components/content/blocks/action_panel/transform_block.ts +9 -0
- package/i18n/ar-SA/components/content/blocks/external_integration/index.ts +5 -0
- package/i18n/ar-SA/components/content/blocks/external_integration/lti_consumer.ts +17 -0
- package/i18n/ar-SA/components/content/blocks/index.ts +7 -0
- package/i18n/ar-SA/components/content/index.ts +5 -0
- package/i18n/ar-SA/components/external_integration/driver/lti1p1.ts +17 -0
- package/i18n/ar-SA/components/external_integration/driver/lti1p3.ts +25 -0
- package/i18n/ar-SA/components/external_integration/driver/scorm.ts +14 -0
- package/i18n/ar-SA/components/external_integration/index.ts +36 -0
- package/i18n/ar-SA/components/external_integration/provider_target.ts +9 -0
- package/i18n/ar-SA/components/file_import/index.ts +5 -0
- package/i18n/ar-SA/components/file_import/resourcespace.ts +4 -0
- package/i18n/ar-SA/components/index.ts +19 -0
- package/i18n/ar-SA/components/integration/driver.ts +67 -0
- package/i18n/ar-SA/components/integration/index.ts +9 -0
- package/i18n/ar-SA/components/integration/job.ts +25 -0
- package/i18n/ar-SA/components/integration/job_log.ts +24 -0
- package/i18n/ar-SA/components/llm/blooms.ts +15 -0
- package/i18n/ar-SA/components/llm/content_selector.ts +3 -0
- package/i18n/ar-SA/components/llm/generate_content/fake_text_stream.ts +62 -0
- package/i18n/ar-SA/components/llm/generate_content/generate_questions.ts +92 -0
- package/i18n/ar-SA/components/llm/generate_content/index.ts +8 -0
- package/i18n/ar-SA/components/llm/index.ts +10 -0
- package/i18n/ar-SA/components/navigation/index.ts +5 -0
- package/i18n/ar-SA/components/navigation/integrations.ts +9 -0
- package/i18n/ar-SA/components/settings/external_integration/index.ts +5 -0
- package/i18n/ar-SA/components/settings/external_integration/lti_consumer.ts +10 -0
- package/i18n/ar-SA/components/settings/index.ts +5 -0
- package/i18n/ar-SA/index.ts +16 -0
- package/i18n/ar-SA/modules/index.ts +5 -0
- package/i18n/ar-SA/pages/admin/index.ts +5 -0
- package/i18n/ar-SA/pages/admin/translateCourse.ts +68 -0
- package/i18n/ar-SA/pages/course/external_integration/index.ts +6 -0
- package/i18n/ar-SA/pages/course/index.ts +5 -0
- package/i18n/ar-SA/pages/importContent.ts +3 -0
- package/i18n/ar-SA/pages/importCourse.ts +13 -0
- package/i18n/ar-SA/pages/index.ts +15 -0
- package/i18n/ar-SA/pages/login/index.ts +9 -0
- package/i18n/ar-SA/pages/login/lti.ts +23 -0
- package/i18n/ar-SA/pages/login/saml.ts +7 -0
- package/i18n/ar-SA/pages/login/scorm.ts +28 -0
- package/i18n/ar-SA/pages/vendor.ts +11 -0
- package/i18n/ar-SA/shared/content_blocks.ts +9 -0
- package/i18n/ar-SA/shared/error.ts +9 -0
- package/i18n/ar-SA/shared/file.ts +5 -0
- package/i18n/ar-SA/shared/index.ts +17 -0
- package/i18n/ar-SA/shared/menu.ts +3 -0
- package/i18n/ar-SA/shared/notification.ts +14 -0
- package/i18n/ar-SA/shared/permission.ts +52 -0
- package/i18n/ar-SA/shared/settings.ts +9 -0
- package/i18n/en-US/components/content/blocks/action_panel/index.ts +2 -0
- package/i18n/en-US/components/content/blocks/action_panel/transform_activity.ts +8 -0
- package/i18n/en-US/components/content/blocks/action_panel/transform_block.ts +1 -1
- package/i18n/en-US/components/content/blocks/external_integration/lti_consumer.ts +1 -0
- package/i18n/en-US/components/integration/job.ts +2 -0
- package/i18n/en-US/components/navigation/integrations.ts +1 -0
- package/i18n/en-US/components/settings/external_integration/lti_consumer.ts +2 -0
- package/i18n/en-US/pages/admin/index.ts +5 -0
- package/i18n/en-US/pages/admin/translateCourse.ts +68 -0
- package/i18n/en-US/pages/index.ts +2 -0
- package/i18n/es-ES/components/content/blocks/action_panel/index.ts +2 -0
- package/i18n/es-ES/components/content/blocks/action_panel/transform_activity.ts +8 -0
- package/i18n/es-ES/components/content/blocks/action_panel/transform_block.ts +1 -1
- package/i18n/es-ES/components/content/blocks/external_integration/lti_consumer.ts +8 -7
- package/i18n/es-ES/components/integration/job.ts +2 -0
- package/i18n/es-ES/components/navigation/integrations.ts +1 -0
- package/i18n/es-ES/components/settings/external_integration/lti_consumer.ts +3 -0
- package/i18n/es-ES/pages/admin/index.ts +5 -0
- package/i18n/es-ES/pages/admin/translateCourse.ts +68 -0
- package/i18n/es-ES/pages/index.ts +2 -0
- package/i18n/fr-FR/components/ai_agent/chat.ts +20 -0
- package/i18n/fr-FR/components/ai_agent/index.ts +5 -0
- package/i18n/fr-FR/components/content/blocks/action_panel/index.ts +5 -0
- package/i18n/fr-FR/components/content/blocks/action_panel/transform_block.ts +9 -0
- package/i18n/fr-FR/components/content/blocks/external_integration/index.ts +5 -0
- package/i18n/fr-FR/components/content/blocks/external_integration/lti_consumer.ts +17 -0
- package/i18n/fr-FR/components/content/blocks/index.ts +7 -0
- package/i18n/fr-FR/components/content/index.ts +5 -0
- package/i18n/fr-FR/components/external_integration/driver/lti1p1.ts +17 -0
- package/i18n/fr-FR/components/external_integration/driver/lti1p3.ts +25 -0
- package/i18n/fr-FR/components/external_integration/driver/scorm.ts +14 -0
- package/i18n/fr-FR/components/external_integration/index.ts +36 -0
- package/i18n/fr-FR/components/external_integration/provider_target.ts +9 -0
- package/i18n/fr-FR/components/file_import/index.ts +5 -0
- package/i18n/fr-FR/components/file_import/resourcespace.ts +4 -0
- package/i18n/fr-FR/components/index.ts +19 -0
- package/i18n/fr-FR/components/integration/driver.ts +67 -0
- package/i18n/fr-FR/components/integration/index.ts +9 -0
- package/i18n/fr-FR/components/integration/job.ts +25 -0
- package/i18n/fr-FR/components/integration/job_log.ts +24 -0
- package/i18n/fr-FR/components/llm/blooms.ts +15 -0
- package/i18n/fr-FR/components/llm/content_selector.ts +3 -0
- package/i18n/fr-FR/components/llm/generate_content/fake_text_stream.ts +62 -0
- package/i18n/fr-FR/components/llm/generate_content/generate_questions.ts +92 -0
- package/i18n/fr-FR/components/llm/generate_content/index.ts +8 -0
- package/i18n/fr-FR/components/llm/index.ts +10 -0
- package/i18n/fr-FR/components/navigation/index.ts +5 -0
- package/i18n/fr-FR/components/navigation/integrations.ts +9 -0
- package/i18n/fr-FR/components/settings/external_integration/index.ts +5 -0
- package/i18n/fr-FR/components/settings/external_integration/lti_consumer.ts +10 -0
- package/i18n/fr-FR/components/settings/index.ts +5 -0
- package/i18n/fr-FR/index.ts +16 -0
- package/i18n/fr-FR/modules/index.ts +5 -0
- package/i18n/fr-FR/pages/admin/index.ts +5 -0
- package/i18n/fr-FR/pages/admin/translateCourse.ts +68 -0
- package/i18n/fr-FR/pages/course/external_integration/index.ts +6 -0
- package/i18n/fr-FR/pages/course/index.ts +5 -0
- package/i18n/fr-FR/pages/importContent.ts +3 -0
- package/i18n/fr-FR/pages/importCourse.ts +13 -0
- package/i18n/fr-FR/pages/index.ts +15 -0
- package/i18n/fr-FR/pages/login/index.ts +9 -0
- package/i18n/fr-FR/pages/login/lti.ts +23 -0
- package/i18n/fr-FR/pages/login/saml.ts +7 -0
- package/i18n/fr-FR/pages/login/scorm.ts +28 -0
- package/i18n/fr-FR/pages/vendor.ts +11 -0
- package/i18n/fr-FR/shared/content_blocks.ts +9 -0
- package/i18n/fr-FR/shared/error.ts +9 -0
- package/i18n/fr-FR/shared/file.ts +5 -0
- package/i18n/fr-FR/shared/index.ts +17 -0
- package/i18n/fr-FR/shared/menu.ts +3 -0
- package/i18n/fr-FR/shared/notification.ts +14 -0
- package/i18n/fr-FR/shared/permission.ts +52 -0
- package/i18n/fr-FR/shared/settings.ts +9 -0
- package/i18n/index.ts +4 -0
- package/i18n/sv-SE/components/content/blocks/action_panel/index.ts +2 -0
- package/i18n/sv-SE/components/content/blocks/action_panel/transform_activity.ts +8 -0
- package/i18n/sv-SE/components/content/blocks/action_panel/transform_block.ts +1 -1
- package/i18n/sv-SE/components/content/blocks/external_integration/lti_consumer.ts +9 -8
- package/i18n/sv-SE/components/integration/job.ts +6 -4
- package/i18n/sv-SE/components/navigation/integrations.ts +1 -0
- package/i18n/sv-SE/components/settings/external_integration/lti_consumer.ts +3 -0
- package/i18n/sv-SE/pages/admin/index.ts +5 -0
- package/i18n/sv-SE/pages/admin/translateCourse.ts +68 -0
- package/i18n/sv-SE/pages/index.ts +2 -0
- package/package.json +1 -1
- package/pages/admin/translateCourse.vue +81 -0
- package/plugin.js +32 -0
|
@@ -0,0 +1,574 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-sheet>
|
|
3
|
+
<v-row>
|
|
4
|
+
<v-col cols="12" md="8">
|
|
5
|
+
<h1 class="headline">
|
|
6
|
+
{{ $t('windward.integrations.pages.admin.translateCourse.title') }}
|
|
7
|
+
</h1>
|
|
8
|
+
<p class="subtitle-1 mb-4">
|
|
9
|
+
{{ $t('windward.integrations.pages.admin.translateCourse.subtitle') }}
|
|
10
|
+
</p>
|
|
11
|
+
|
|
12
|
+
<!-- Step 1: Source Language Selection -->
|
|
13
|
+
<v-autocomplete
|
|
14
|
+
v-model="sourceLocaleId"
|
|
15
|
+
:items="availableLocales"
|
|
16
|
+
item-text="displayName"
|
|
17
|
+
item-value="id"
|
|
18
|
+
:label="$t('windward.integrations.pages.admin.translateCourse.source_language')"
|
|
19
|
+
:loading="loadingLocales"
|
|
20
|
+
:disabled="loadingLocales"
|
|
21
|
+
clearable
|
|
22
|
+
@change="onSourceLocaleChange"
|
|
23
|
+
>
|
|
24
|
+
<template #item="{ item }">
|
|
25
|
+
<v-list-item-content>
|
|
26
|
+
<v-list-item-title>
|
|
27
|
+
{{ item.displayName }}
|
|
28
|
+
</v-list-item-title>
|
|
29
|
+
</v-list-item-content>
|
|
30
|
+
</template>
|
|
31
|
+
</v-autocomplete>
|
|
32
|
+
|
|
33
|
+
<!-- Step 2: Course Selection -->
|
|
34
|
+
<v-autocomplete
|
|
35
|
+
v-if="sourceLocaleId"
|
|
36
|
+
v-model="selectedCourseId"
|
|
37
|
+
:items="coursesInSourceLanguage"
|
|
38
|
+
item-text="name"
|
|
39
|
+
item-value="id"
|
|
40
|
+
:label="$t('windward.integrations.pages.admin.translateCourse.course')"
|
|
41
|
+
:loading="loadingCourses"
|
|
42
|
+
:disabled="loadingCourses"
|
|
43
|
+
clearable
|
|
44
|
+
@change="onCourseChange"
|
|
45
|
+
>
|
|
46
|
+
<template #item="{ item }">
|
|
47
|
+
<v-list-item-content>
|
|
48
|
+
<v-list-item-title>
|
|
49
|
+
{{ item.name }}
|
|
50
|
+
</v-list-item-title>
|
|
51
|
+
<v-list-item-subtitle>
|
|
52
|
+
{{ item.status }} • {{ item.ownerName || $t('windward.integrations.pages.admin.translateCourse.no_owner') }}
|
|
53
|
+
</v-list-item-subtitle>
|
|
54
|
+
</v-list-item-content>
|
|
55
|
+
</template>
|
|
56
|
+
<template #no-data>
|
|
57
|
+
<v-list-item>
|
|
58
|
+
<v-list-item-content>
|
|
59
|
+
<v-list-item-title>
|
|
60
|
+
{{ $t('windward.integrations.pages.admin.translateCourse.no_courses_found', [sourceLocaleName]) }}
|
|
61
|
+
</v-list-item-title>
|
|
62
|
+
</v-list-item-content>
|
|
63
|
+
</v-list-item>
|
|
64
|
+
</template>
|
|
65
|
+
</v-autocomplete>
|
|
66
|
+
|
|
67
|
+
<!-- Step 3: Target Language Selection -->
|
|
68
|
+
<v-autocomplete
|
|
69
|
+
v-if="selectedCourseId"
|
|
70
|
+
v-model="targetLocaleId"
|
|
71
|
+
:items="targetLocaleOptions"
|
|
72
|
+
item-text="displayName"
|
|
73
|
+
item-value="id"
|
|
74
|
+
:label="$t('windward.integrations.pages.admin.translateCourse.target_language')"
|
|
75
|
+
:loading="loadingLocales"
|
|
76
|
+
:disabled="loadingLocales"
|
|
77
|
+
clearable
|
|
78
|
+
@change="onTargetLocaleChange"
|
|
79
|
+
>
|
|
80
|
+
<template #item="{ item }">
|
|
81
|
+
<v-list-item-content>
|
|
82
|
+
<v-list-item-title>
|
|
83
|
+
{{ item.displayName }}
|
|
84
|
+
</v-list-item-title>
|
|
85
|
+
</v-list-item-content>
|
|
86
|
+
</template>
|
|
87
|
+
</v-autocomplete>
|
|
88
|
+
|
|
89
|
+
<v-switch
|
|
90
|
+
v-if="selectedCourseId"
|
|
91
|
+
v-model="sendEmail"
|
|
92
|
+
:label="$t('windward.integrations.pages.admin.translateCourse.send_email_notification')"
|
|
93
|
+
></v-switch>
|
|
94
|
+
|
|
95
|
+
<!-- Translation Summary -->
|
|
96
|
+
<v-card v-if="selectedCourse && targetLocaleId" outlined class="mb-4">
|
|
97
|
+
<v-card-title class="text-subtitle-1">
|
|
98
|
+
{{ $t('windward.integrations.pages.admin.translateCourse.summary_title') }}
|
|
99
|
+
</v-card-title>
|
|
100
|
+
<v-card-text>
|
|
101
|
+
<v-simple-table>
|
|
102
|
+
<tbody>
|
|
103
|
+
<tr>
|
|
104
|
+
<td class="font-weight-bold" style="width: 150px;">{{ $t('windward.integrations.pages.admin.translateCourse.source_course') }}</td>
|
|
105
|
+
<td>{{ selectedCourse.name }}</td>
|
|
106
|
+
</tr>
|
|
107
|
+
<tr>
|
|
108
|
+
<td class="font-weight-bold">{{ $t('windward.integrations.pages.admin.translateCourse.source_language_label') }}</td>
|
|
109
|
+
<td>{{ sourceLocaleName }}</td>
|
|
110
|
+
</tr>
|
|
111
|
+
<tr>
|
|
112
|
+
<td class="font-weight-bold">{{ $t('windward.integrations.pages.admin.translateCourse.target_language_label') }}</td>
|
|
113
|
+
<td>{{ targetLocaleName }}</td>
|
|
114
|
+
</tr>
|
|
115
|
+
</tbody>
|
|
116
|
+
</v-simple-table>
|
|
117
|
+
</v-card-text>
|
|
118
|
+
</v-card>
|
|
119
|
+
|
|
120
|
+
<!-- Action Buttons -->
|
|
121
|
+
<v-card-actions>
|
|
122
|
+
<v-spacer></v-spacer>
|
|
123
|
+
<v-btn
|
|
124
|
+
text
|
|
125
|
+
@click="reset"
|
|
126
|
+
>
|
|
127
|
+
{{ $t('windward.integrations.pages.admin.translateCourse.reset_button') }}
|
|
128
|
+
</v-btn>
|
|
129
|
+
<v-btn
|
|
130
|
+
color="primary"
|
|
131
|
+
:disabled="!canTranslate"
|
|
132
|
+
:loading="translating"
|
|
133
|
+
@click="startTranslation"
|
|
134
|
+
>
|
|
135
|
+
{{ $t('windward.integrations.pages.admin.translateCourse.start_translation_button') }}
|
|
136
|
+
</v-btn>
|
|
137
|
+
</v-card-actions>
|
|
138
|
+
</v-col>
|
|
139
|
+
</v-row>
|
|
140
|
+
|
|
141
|
+
<!-- DIALOG 1: Retranslation Mode Selection -->
|
|
142
|
+
<v-dialog v-model="showRetranslationDialog" max-width="600" persistent>
|
|
143
|
+
<v-card>
|
|
144
|
+
<v-card-title>
|
|
145
|
+
<v-icon color="warning" class="mr-2">mdi-alert-circle</v-icon>
|
|
146
|
+
{{ $t('windward.integrations.pages.admin.translateCourse.retranslation_dialog.title') }}
|
|
147
|
+
</v-card-title>
|
|
148
|
+
|
|
149
|
+
<v-card-text>
|
|
150
|
+
<v-alert type="info" text class="mb-4">
|
|
151
|
+
<span v-html="$t('windward.integrations.pages.admin.translateCourse.retranslation_dialog.existing_translation_info', [targetLocaleName])"></span>
|
|
152
|
+
<br><br>
|
|
153
|
+
<strong>{{ existingTranslation ? existingTranslation.name : '' }}</strong>
|
|
154
|
+
</v-alert>
|
|
155
|
+
|
|
156
|
+
<p class="mb-4">{{ $t('windward.integrations.pages.admin.translateCourse.retranslation_dialog.choose_how_to_proceed') }}</p>
|
|
157
|
+
|
|
158
|
+
<v-radio-group v-model="retranslationMode">
|
|
159
|
+
<v-radio value="incremental" class="mb-4">
|
|
160
|
+
<template #label>
|
|
161
|
+
<div>
|
|
162
|
+
<strong class="success--text">{{ $t('windward.integrations.pages.admin.translateCourse.retranslation_dialog.incremental_title') }}</strong> {{ $t('windward.integrations.pages.admin.translateCourse.retranslation_dialog.incremental_subtitle') }}
|
|
163
|
+
<div class="text-caption text--secondary">
|
|
164
|
+
{{ $t('windward.integrations.pages.admin.translateCourse.retranslation_dialog.incremental_description') }}
|
|
165
|
+
<br>
|
|
166
|
+
<strong>{{ $t('windward.integrations.pages.admin.translateCourse.retranslation_dialog.incremental_safe_note') }}</strong>
|
|
167
|
+
</div>
|
|
168
|
+
</div>
|
|
169
|
+
</template>
|
|
170
|
+
</v-radio>
|
|
171
|
+
|
|
172
|
+
<v-radio value="full">
|
|
173
|
+
<template #label>
|
|
174
|
+
<div>
|
|
175
|
+
<strong class="error--text">{{ $t('windward.integrations.pages.admin.translateCourse.retranslation_dialog.full_title') }}</strong>
|
|
176
|
+
<div class="text-caption text--secondary">
|
|
177
|
+
<strong class="error--text">{{ $t('windward.integrations.pages.admin.translateCourse.retranslation_dialog.full_warning') }}</strong> {{ $t('windward.integrations.pages.admin.translateCourse.retranslation_dialog.full_description') }}
|
|
178
|
+
</div>
|
|
179
|
+
</div>
|
|
180
|
+
</template>
|
|
181
|
+
</v-radio>
|
|
182
|
+
</v-radio-group>
|
|
183
|
+
</v-card-text>
|
|
184
|
+
|
|
185
|
+
<v-card-actions>
|
|
186
|
+
<v-spacer></v-spacer>
|
|
187
|
+
<v-btn text @click="cancelRetranslation">
|
|
188
|
+
{{ $t('windward.integrations.pages.admin.translateCourse.retranslation_dialog.cancel_button') }}
|
|
189
|
+
</v-btn>
|
|
190
|
+
<v-btn
|
|
191
|
+
color="primary"
|
|
192
|
+
@click="proceedToConfirmation"
|
|
193
|
+
>
|
|
194
|
+
{{ $t('windward.integrations.pages.admin.translateCourse.retranslation_dialog.continue_button') }}
|
|
195
|
+
</v-btn>
|
|
196
|
+
</v-card-actions>
|
|
197
|
+
</v-card>
|
|
198
|
+
</v-dialog>
|
|
199
|
+
|
|
200
|
+
<!-- DIALOG 2: Nuclear Option Confirmation (Double Check) -->
|
|
201
|
+
<v-dialog v-model="showDeleteConfirmDialog" max-width="500" persistent>
|
|
202
|
+
<v-card>
|
|
203
|
+
<v-card-title class="error--text">
|
|
204
|
+
<v-icon color="error" class="mr-2">mdi-alert</v-icon>
|
|
205
|
+
{{ $t('windward.integrations.pages.admin.translateCourse.delete_confirm_dialog.title') }}
|
|
206
|
+
</v-card-title>
|
|
207
|
+
|
|
208
|
+
<v-card-text>
|
|
209
|
+
<v-alert type="error" prominent class="mb-4">
|
|
210
|
+
<strong>{{ $t('windward.integrations.pages.admin.translateCourse.delete_confirm_dialog.cannot_undo') }}</strong>
|
|
211
|
+
</v-alert>
|
|
212
|
+
|
|
213
|
+
<p class="mb-3">
|
|
214
|
+
{{ $t('windward.integrations.pages.admin.translateCourse.delete_confirm_dialog.about_to_delete') }}
|
|
215
|
+
</p>
|
|
216
|
+
|
|
217
|
+
<v-card outlined class="mb-4">
|
|
218
|
+
<v-card-text>
|
|
219
|
+
<div class="text-subtitle-2">{{ existingTranslation ? existingTranslation.name : '' }}</div>
|
|
220
|
+
<div class="text-caption text--secondary">
|
|
221
|
+
{{ $t('windward.integrations.pages.admin.translateCourse.delete_confirm_dialog.course_id') }} {{ existingTranslation ? existingTranslation.id : '' }}
|
|
222
|
+
</div>
|
|
223
|
+
</v-card-text>
|
|
224
|
+
</v-card>
|
|
225
|
+
|
|
226
|
+
<p class="mb-3">
|
|
227
|
+
{{ $t('windward.integrations.pages.admin.translateCourse.delete_confirm_dialog.will_delete_title') }}
|
|
228
|
+
</p>
|
|
229
|
+
<ul class="mb-4">
|
|
230
|
+
<li>{{ $t('windward.integrations.pages.admin.translateCourse.delete_confirm_dialog.will_delete_content') }}</li>
|
|
231
|
+
<li>{{ $t('windward.integrations.pages.admin.translateCourse.delete_confirm_dialog.will_delete_assessments') }}</li>
|
|
232
|
+
<li>{{ $t('windward.integrations.pages.admin.translateCourse.delete_confirm_dialog.will_delete_files') }}</li>
|
|
233
|
+
<li>{{ $t('windward.integrations.pages.admin.translateCourse.delete_confirm_dialog.will_delete_progress') }}</li>
|
|
234
|
+
</ul>
|
|
235
|
+
|
|
236
|
+
<p class="mb-2">
|
|
237
|
+
<strong>{{ $t('windward.integrations.pages.admin.translateCourse.delete_confirm_dialog.are_you_sure') }}</strong>
|
|
238
|
+
</p>
|
|
239
|
+
|
|
240
|
+
<!-- Require typing confirmation -->
|
|
241
|
+
<v-text-field
|
|
242
|
+
v-model="deleteConfirmationText"
|
|
243
|
+
:label="$t('windward.integrations.pages.admin.translateCourse.delete_confirm_dialog.type_delete_to_confirm')"
|
|
244
|
+
outlined
|
|
245
|
+
dense
|
|
246
|
+
class="mt-4"
|
|
247
|
+
:error="deleteConfirmationText && deleteConfirmationText !== 'DELETE'"
|
|
248
|
+
:hint="$t('windward.integrations.pages.admin.translateCourse.delete_confirm_dialog.type_exactly_delete')"
|
|
249
|
+
persistent-hint
|
|
250
|
+
></v-text-field>
|
|
251
|
+
</v-card-text>
|
|
252
|
+
|
|
253
|
+
<v-card-actions>
|
|
254
|
+
<v-spacer></v-spacer>
|
|
255
|
+
<v-btn
|
|
256
|
+
text
|
|
257
|
+
@click="cancelDeleteConfirmation"
|
|
258
|
+
>
|
|
259
|
+
{{ $t('windward.integrations.pages.admin.translateCourse.delete_confirm_dialog.cancel_button') }}
|
|
260
|
+
</v-btn>
|
|
261
|
+
<v-btn
|
|
262
|
+
color="error"
|
|
263
|
+
:disabled="deleteConfirmationText !== 'DELETE'"
|
|
264
|
+
:loading="translating"
|
|
265
|
+
@click="confirmRetranslation"
|
|
266
|
+
>
|
|
267
|
+
{{ $t('windward.integrations.pages.admin.translateCourse.delete_confirm_dialog.confirm_button') }}
|
|
268
|
+
</v-btn>
|
|
269
|
+
</v-card-actions>
|
|
270
|
+
</v-card>
|
|
271
|
+
</v-dialog>
|
|
272
|
+
</v-sheet>
|
|
273
|
+
</template>
|
|
274
|
+
|
|
275
|
+
<script>
|
|
276
|
+
import { mapGetters } from 'vuex'
|
|
277
|
+
import Locale from '~/models/Locale'
|
|
278
|
+
import Course from '~/models/Course'
|
|
279
|
+
import Organization from '~/models/Organization'
|
|
280
|
+
|
|
281
|
+
export default {
|
|
282
|
+
name: 'TranslateCourse',
|
|
283
|
+
data() {
|
|
284
|
+
return {
|
|
285
|
+
// Locale data
|
|
286
|
+
availableLocales: [],
|
|
287
|
+
loadingLocales: false,
|
|
288
|
+
|
|
289
|
+
// Source language selection
|
|
290
|
+
sourceLocaleId: null,
|
|
291
|
+
|
|
292
|
+
// Course selection
|
|
293
|
+
selectedCourseId: null,
|
|
294
|
+
selectedCourse: null,
|
|
295
|
+
coursesInSourceLanguage: [],
|
|
296
|
+
loadingCourses: false,
|
|
297
|
+
|
|
298
|
+
// Target language selection
|
|
299
|
+
targetLocaleId: null,
|
|
300
|
+
|
|
301
|
+
// Options
|
|
302
|
+
sendEmail: true,
|
|
303
|
+
|
|
304
|
+
// Translation state
|
|
305
|
+
translating: false,
|
|
306
|
+
|
|
307
|
+
// Retranslation dialog states
|
|
308
|
+
showRetranslationDialog: false,
|
|
309
|
+
showDeleteConfirmDialog: false,
|
|
310
|
+
retranslationMode: 'incremental',
|
|
311
|
+
existingTranslation: null,
|
|
312
|
+
deleteConfirmationText: '',
|
|
313
|
+
}
|
|
314
|
+
},
|
|
315
|
+
computed: {
|
|
316
|
+
...mapGetters({
|
|
317
|
+
organization: 'organization/get',
|
|
318
|
+
}),
|
|
319
|
+
organizationModel() {
|
|
320
|
+
return new Organization({ id: this.organization.id })
|
|
321
|
+
},
|
|
322
|
+
canTranslate() {
|
|
323
|
+
return this.selectedCourse && this.targetLocaleId && !this.translating
|
|
324
|
+
},
|
|
325
|
+
sourceLocaleName() {
|
|
326
|
+
if (!this.sourceLocaleId) return ''
|
|
327
|
+
const locale = this.availableLocales.find(l => l.id === this.sourceLocaleId)
|
|
328
|
+
return locale ? locale.displayName : ''
|
|
329
|
+
},
|
|
330
|
+
targetLocaleName() {
|
|
331
|
+
if (!this.targetLocaleId) return ''
|
|
332
|
+
const locale = this.availableLocales.find(l => l.id === this.targetLocaleId)
|
|
333
|
+
return locale ? locale.displayName : ''
|
|
334
|
+
},
|
|
335
|
+
// Filter out source language from target options
|
|
336
|
+
targetLocaleOptions() {
|
|
337
|
+
return this.availableLocales.filter(l => l.id !== this.sourceLocaleId)
|
|
338
|
+
},
|
|
339
|
+
},
|
|
340
|
+
async mounted() {
|
|
341
|
+
await this.loadLocales()
|
|
342
|
+
},
|
|
343
|
+
methods: {
|
|
344
|
+
async loadLocales() {
|
|
345
|
+
this.loadingLocales = true
|
|
346
|
+
try {
|
|
347
|
+
const locales = await new Locale().get()
|
|
348
|
+
this.availableLocales = locales.map(locale => {
|
|
349
|
+
// Use i18n translation for full language name (e.g., 'en-US' → 'English US')
|
|
350
|
+
const i18nKey = `locales.${locale.name}`
|
|
351
|
+
const translatedName = this.$t(i18nKey)
|
|
352
|
+
// Get the native language name, fallback to raw name if not found
|
|
353
|
+
const nativeName = translatedName !== i18nKey ? translatedName : locale.name
|
|
354
|
+
// Add locale code next to the language name for clarity
|
|
355
|
+
const displayName = `${nativeName} (${locale.name})`
|
|
356
|
+
return {
|
|
357
|
+
id: locale.id,
|
|
358
|
+
name: locale.name,
|
|
359
|
+
displayName,
|
|
360
|
+
}
|
|
361
|
+
})
|
|
362
|
+
} catch (e) {
|
|
363
|
+
// eslint-disable-next-line no-console
|
|
364
|
+
console.error('Error loading locales:', e)
|
|
365
|
+
this.$dialog.error(this.$t('windward.integrations.pages.admin.translateCourse.locale_load_failed'))
|
|
366
|
+
} finally {
|
|
367
|
+
this.loadingLocales = false
|
|
368
|
+
}
|
|
369
|
+
},
|
|
370
|
+
|
|
371
|
+
async onSourceLocaleChange() {
|
|
372
|
+
// Clear dependent selections
|
|
373
|
+
this.selectedCourseId = null
|
|
374
|
+
this.selectedCourse = null
|
|
375
|
+
this.targetLocaleId = null
|
|
376
|
+
|
|
377
|
+
if (this.sourceLocaleId) {
|
|
378
|
+
await this.loadCoursesForLocale()
|
|
379
|
+
} else {
|
|
380
|
+
this.coursesInSourceLanguage = []
|
|
381
|
+
}
|
|
382
|
+
},
|
|
383
|
+
|
|
384
|
+
async loadCoursesForLocale() {
|
|
385
|
+
this.loadingCourses = true
|
|
386
|
+
this.coursesInSourceLanguage = []
|
|
387
|
+
|
|
388
|
+
try {
|
|
389
|
+
// Fetch courses filtered by locale_id
|
|
390
|
+
const response = await new Organization({ id: this.organization.id })
|
|
391
|
+
.courses()
|
|
392
|
+
.include('user', 'locale')
|
|
393
|
+
.where('locale_id', this.sourceLocaleId)
|
|
394
|
+
.limit(100)
|
|
395
|
+
.nowrap()
|
|
396
|
+
.get()
|
|
397
|
+
|
|
398
|
+
this.coursesInSourceLanguage = response.data.map(course => ({
|
|
399
|
+
id: course.id,
|
|
400
|
+
name: course.name,
|
|
401
|
+
status: course.status,
|
|
402
|
+
ownerName: course.user
|
|
403
|
+
? `${course.user.first_name} ${course.user.last_name}`
|
|
404
|
+
: null,
|
|
405
|
+
...course,
|
|
406
|
+
}))
|
|
407
|
+
} catch (e) {
|
|
408
|
+
// eslint-disable-next-line no-console
|
|
409
|
+
console.error('Error loading courses:', e)
|
|
410
|
+
this.$dialog.error(this.$t('windward.integrations.pages.admin.translateCourse.courses_load_failed'))
|
|
411
|
+
} finally {
|
|
412
|
+
this.loadingCourses = false
|
|
413
|
+
}
|
|
414
|
+
},
|
|
415
|
+
|
|
416
|
+
onCourseChange() {
|
|
417
|
+
// Clear target locale when course changes
|
|
418
|
+
this.targetLocaleId = null
|
|
419
|
+
|
|
420
|
+
// Find the selected course object
|
|
421
|
+
this.selectedCourse = this.coursesInSourceLanguage.find(
|
|
422
|
+
c => c.id === this.selectedCourseId
|
|
423
|
+
) || null
|
|
424
|
+
},
|
|
425
|
+
|
|
426
|
+
onTargetLocaleChange() {
|
|
427
|
+
// Validate selection if needed
|
|
428
|
+
},
|
|
429
|
+
|
|
430
|
+
async startTranslation() {
|
|
431
|
+
this.translating = true
|
|
432
|
+
try {
|
|
433
|
+
const course = new Course({ id: this.selectedCourseId })
|
|
434
|
+
|
|
435
|
+
await course.request({
|
|
436
|
+
method: 'POST',
|
|
437
|
+
url: `${course.endpoint()}/translate`,
|
|
438
|
+
data: {
|
|
439
|
+
target_locale_id: this.targetLocaleId,
|
|
440
|
+
options: {
|
|
441
|
+
send_email: this.sendEmail,
|
|
442
|
+
},
|
|
443
|
+
},
|
|
444
|
+
})
|
|
445
|
+
|
|
446
|
+
// Success - show message and emit event
|
|
447
|
+
this.$dialog.success(this.$t('windward.integrations.pages.admin.translateCourse.translation_queued'))
|
|
448
|
+
this.$emit('translation-started')
|
|
449
|
+
this.reset()
|
|
450
|
+
|
|
451
|
+
} catch (e) {
|
|
452
|
+
// eslint-disable-next-line no-console
|
|
453
|
+
console.error('Translation API Error:', e.response?.status, e.response?.data)
|
|
454
|
+
|
|
455
|
+
// Check if translation exists and requires retranslation mode
|
|
456
|
+
if (e.response?.status === 422 && e.response?.data?.requires_retranslation_mode) {
|
|
457
|
+
// Translation exists - show mode selection dialog
|
|
458
|
+
this.existingTranslation = {
|
|
459
|
+
id: e.response.data.existing_course_id,
|
|
460
|
+
name: e.response.data.existing_course_name,
|
|
461
|
+
}
|
|
462
|
+
this.showRetranslationDialog = true
|
|
463
|
+
} else {
|
|
464
|
+
// eslint-disable-next-line no-console
|
|
465
|
+
console.error('Error starting translation:', e)
|
|
466
|
+
this.$dialog.error(
|
|
467
|
+
e.response?.data?.message || this.$t('windward.integrations.pages.admin.translateCourse.translation_failed')
|
|
468
|
+
)
|
|
469
|
+
}
|
|
470
|
+
} finally {
|
|
471
|
+
this.translating = false
|
|
472
|
+
}
|
|
473
|
+
},
|
|
474
|
+
|
|
475
|
+
/**
|
|
476
|
+
* Proceed from mode selection to confirmation
|
|
477
|
+
*/
|
|
478
|
+
proceedToConfirmation() {
|
|
479
|
+
if (this.retranslationMode === 'full') {
|
|
480
|
+
// Show second confirmation dialog for nuclear option
|
|
481
|
+
this.showRetranslationDialog = false
|
|
482
|
+
this.showDeleteConfirmDialog = true
|
|
483
|
+
} else {
|
|
484
|
+
// Incremental mode - proceed directly
|
|
485
|
+
this.showRetranslationDialog = false
|
|
486
|
+
this.confirmRetranslation()
|
|
487
|
+
}
|
|
488
|
+
},
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
* Cancel retranslation dialog
|
|
492
|
+
*/
|
|
493
|
+
cancelRetranslation() {
|
|
494
|
+
this.showRetranslationDialog = false
|
|
495
|
+
this.retranslationMode = 'incremental' // Reset to default
|
|
496
|
+
this.existingTranslation = null
|
|
497
|
+
this.translating = false
|
|
498
|
+
},
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
* Cancel delete confirmation dialog - go back to mode selection
|
|
502
|
+
*/
|
|
503
|
+
cancelDeleteConfirmation() {
|
|
504
|
+
this.showDeleteConfirmDialog = false
|
|
505
|
+
this.deleteConfirmationText = '' // Reset
|
|
506
|
+
this.showRetranslationDialog = true // Go back to mode selection
|
|
507
|
+
this.translating = false
|
|
508
|
+
},
|
|
509
|
+
|
|
510
|
+
/**
|
|
511
|
+
* Confirm and execute retranslation
|
|
512
|
+
*/
|
|
513
|
+
async confirmRetranslation() {
|
|
514
|
+
this.translating = true
|
|
515
|
+
try {
|
|
516
|
+
const course = new Course({ id: this.selectedCourseId })
|
|
517
|
+
|
|
518
|
+
await course.request({
|
|
519
|
+
method: 'POST',
|
|
520
|
+
url: `${course.endpoint()}/translate`,
|
|
521
|
+
data: {
|
|
522
|
+
target_locale_id: this.targetLocaleId,
|
|
523
|
+
retranslation_mode: this.retranslationMode,
|
|
524
|
+
options: {
|
|
525
|
+
send_email: this.sendEmail,
|
|
526
|
+
},
|
|
527
|
+
},
|
|
528
|
+
})
|
|
529
|
+
|
|
530
|
+
// Show appropriate success message
|
|
531
|
+
if (this.retranslationMode === 'full') {
|
|
532
|
+
this.$dialog.success(this.$t('windward.integrations.pages.admin.translateCourse.full_retranslation_queued'))
|
|
533
|
+
} else {
|
|
534
|
+
this.$dialog.success(this.$t('windward.integrations.pages.admin.translateCourse.incremental_retranslation_queued'))
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
// Emit event and reset form
|
|
538
|
+
this.$emit('translation-started')
|
|
539
|
+
this.reset()
|
|
540
|
+
|
|
541
|
+
} catch (e) {
|
|
542
|
+
// eslint-disable-next-line no-console
|
|
543
|
+
console.error('Error starting retranslation:', e)
|
|
544
|
+
this.$dialog.error(
|
|
545
|
+
e.response?.data?.message || this.$t('windward.integrations.pages.admin.translateCourse.retranslation_failed')
|
|
546
|
+
)
|
|
547
|
+
} finally {
|
|
548
|
+
this.translating = false
|
|
549
|
+
}
|
|
550
|
+
},
|
|
551
|
+
|
|
552
|
+
reset() {
|
|
553
|
+
this.sourceLocaleId = null
|
|
554
|
+
this.selectedCourseId = null
|
|
555
|
+
this.selectedCourse = null
|
|
556
|
+
this.coursesInSourceLanguage = []
|
|
557
|
+
this.targetLocaleId = null
|
|
558
|
+
this.translating = false
|
|
559
|
+
// Reset retranslation state
|
|
560
|
+
this.showRetranslationDialog = false
|
|
561
|
+
this.showDeleteConfirmDialog = false
|
|
562
|
+
this.retranslationMode = 'incremental'
|
|
563
|
+
this.existingTranslation = null
|
|
564
|
+
this.deleteConfirmationText = ''
|
|
565
|
+
},
|
|
566
|
+
},
|
|
567
|
+
}
|
|
568
|
+
</script>
|
|
569
|
+
|
|
570
|
+
<style scoped>
|
|
571
|
+
.v-card {
|
|
572
|
+
transition: all 0.3s ease;
|
|
573
|
+
}
|
|
574
|
+
</style>
|
|
@@ -12,6 +12,33 @@
|
|
|
12
12
|
'windward.integrations.components.settings.external_integration.lti_consumer.link_select'
|
|
13
13
|
)
|
|
14
14
|
}}
|
|
15
|
+
<v-alert v-if="!consumers.length" type="warning">
|
|
16
|
+
<p>
|
|
17
|
+
{{
|
|
18
|
+
$t(
|
|
19
|
+
'windward.integrations.components.settings.external_integration.lti_consumer.no_links'
|
|
20
|
+
)
|
|
21
|
+
}}
|
|
22
|
+
</p>
|
|
23
|
+
<p
|
|
24
|
+
v-if="
|
|
25
|
+
$PermissionService.userHasAccessTo(
|
|
26
|
+
'plugin.windward.integrations.course.externalIntegration',
|
|
27
|
+
'readable'
|
|
28
|
+
)
|
|
29
|
+
"
|
|
30
|
+
>
|
|
31
|
+
<NuxtLink
|
|
32
|
+
:to="'/course/' + course.id + '/integrations/external'"
|
|
33
|
+
>
|
|
34
|
+
{{
|
|
35
|
+
$t(
|
|
36
|
+
'windward.integrations.components.settings.external_integration.lti_consumer.create_link'
|
|
37
|
+
)
|
|
38
|
+
}}
|
|
39
|
+
</NuxtLink>
|
|
40
|
+
</p>
|
|
41
|
+
</v-alert>
|
|
15
42
|
<v-list>
|
|
16
43
|
<v-list-item-group
|
|
17
44
|
v-model="block.metadata.config.tool_id"
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
new_chat: 'New Chat',
|
|
3
|
+
recent_chats: 'Recent chats',
|
|
4
|
+
untitled_chat: 'Untitled chat',
|
|
5
|
+
no_history: 'No recent chats',
|
|
6
|
+
system_tip:
|
|
7
|
+
"Hi! I'm here to help with your course. Try asking about learning objectives, content structure, or best practices.",
|
|
8
|
+
placeholder: 'Ask about your course content...',
|
|
9
|
+
hint: 'Press Enter to send, Shift+Enter for new line',
|
|
10
|
+
error_generic: 'Something went wrong. Please try again.',
|
|
11
|
+
error_with_status:
|
|
12
|
+
'Something went wrong. Please try again. (Error {status})',
|
|
13
|
+
action_try_again: 'Try again',
|
|
14
|
+
action_dismiss: 'Dismiss',
|
|
15
|
+
sender_you: 'You',
|
|
16
|
+
sender_agent: 'Assistant',
|
|
17
|
+
limit_reached:
|
|
18
|
+
'You have reached the maximum number of messages allowed in this chat. Please start a new chat to continue.',
|
|
19
|
+
aria_open_history: 'Open chat history',
|
|
20
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
change_block_type: 'Change block type',
|
|
3
|
+
change_block_type_insufficient_paragraphs:
|
|
4
|
+
'Change block type is available when the text has at least two paragraphs.',
|
|
5
|
+
change_block_type_insufficient_items:
|
|
6
|
+
'Change block type is available when the block has at least two items.',
|
|
7
|
+
change_block_type_error:
|
|
8
|
+
'Unable to change block type. Try again or edit manually.',
|
|
9
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
title: 'LTI Link',
|
|
3
|
+
instructions:
|
|
4
|
+
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam fringilla ipsum eget ante tempus blandit. Maecenas vel massa\n' +
|
|
5
|
+
'nec tellus vestibulum porttitor non a enim.',
|
|
6
|
+
launch: 'Launch',
|
|
7
|
+
goodbye: 'goodbye',
|
|
8
|
+
launch_in_new_window: 'launch {0} in new tab',
|
|
9
|
+
launch_in_modal: 'launch {0} in modal',
|
|
10
|
+
configure_warning:
|
|
11
|
+
'Select an available LTI link to get started. Then, configure the desired launch type.',
|
|
12
|
+
no_access:
|
|
13
|
+
'You do not have permissions to launch this link. Please contact your system administrator.',
|
|
14
|
+
missing_tool: 'The tool id {0} is missing',
|
|
15
|
+
unknown_error: 'Something went wrong! Could not launch this link!',
|
|
16
|
+
link_disabled: 'Link disabled',
|
|
17
|
+
}
|