@windward/core 0.14.0 → 0.16.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 +6 -0
- package/bitbucket-pipelines.yml +8 -0
- package/components/Content/Blocks/BlockQuote.vue +51 -47
- package/components/Content/Blocks/GenerateAIQuestionButton.vue +151 -37
- package/components/Content/Blocks/OpenResponse.vue +11 -3
- package/components/Content/Blocks/UserUpload/ManageDataTableUserFiles.vue +2 -11
- package/components/Content/Blocks/Video.vue +1 -1
- package/components/Glossary/GlossaryVerification.vue +240 -0
- package/components/Navigation/Items/GlossaryNav.vue +8 -2
- package/components/Navigation/Items/UserUploadNav.vue +32 -13
- package/components/Settings/AccordionSettings.vue +37 -27
- package/components/Settings/ClickableIconsSettings.vue +1 -0
- package/components/Settings/ImageSettings.vue +5 -12
- package/components/Settings/TabSettings.vue +33 -23
- package/components/Settings/TextEditorSettings.vue +16 -245
- package/components/Settings/VideoSettings.vue +1 -1
- package/components/utils/ContentViewer.vue +3 -3
- package/components/utils/TinyMCEWrapper.vue +24 -14
- package/components/utils/glossary/CourseGlossary.vue +75 -95
- package/components/utils/glossary/CourseGlossaryForm.vue +42 -13
- package/components/utils/glossary/GlossaryToolTip.vue +7 -11
- package/helpers/GlossaryHelper.ts +18 -16
- package/i18n/en-US/components/content/blocks/generate_questions.ts +26 -11
- package/i18n/en-US/pages/glossary.ts +3 -1
- package/i18n/en-US/shared/content_blocks.ts +1 -1
- package/i18n/en-US/shared/notification.ts +5 -0
- package/i18n/en-US/shared/permission.ts +4 -0
- package/i18n/en-US/shared/settings.ts +1 -1
- package/i18n/es-ES/components/content/blocks/generate_questions.ts +11 -1
- package/i18n/es-ES/pages/glossary.ts +3 -1
- package/i18n/es-ES/shared/content_blocks.ts +1 -1
- package/i18n/es-ES/shared/notification.ts +5 -0
- package/i18n/es-ES/shared/permission.ts +8 -4
- package/i18n/es-ES/shared/settings.ts +1 -2
- package/i18n/sv-SE/components/content/blocks/generate_questions.ts +11 -1
- package/i18n/sv-SE/pages/glossary.ts +3 -1
- package/i18n/sv-SE/shared/content_blocks.ts +1 -1
- package/i18n/sv-SE/shared/notification.ts +4 -0
- package/i18n/sv-SE/shared/permission.ts +8 -4
- package/i18n/sv-SE/shared/settings.ts +1 -1
- package/jest.config.js +3 -0
- package/models/BaseModel.ts +16 -0
- package/models/CourseGlossaryTerm.ts +22 -0
- package/models/UserFileAsset.ts +1 -0
- package/package.json +4 -3
- package/pages/glossary.vue +41 -4
- package/pages/userUpload.vue +70 -47
- package/plugin.js +34 -12
- package/store/glossary.js +57 -0
- package/test/Components/Content/Blocks/Feedback.spec.js +3 -1
- package/test/Components/Content/Blocks/Video.spec.js +2 -2
- package/test/Components/Glossary/GlossaryVerification.spec.js +19 -0
- package/test/Components/utils/glossary/CourseGlossary.spec.js +19 -0
- package/test/Components/utils/glossary/CourseGlossaryForm.spec.js +28 -0
- package/test/__mocks__/helpersMock.js +0 -24
- package/test/__mocks__/modelMock.js +5 -0
- package/test/helpers/GlossaryHelper.spec.js +32 -14
- package/test/mocks.js +11 -0
- package/test/setup/before.js +15 -0
- package/helpers/GlossaryTerm.ts +0 -31
|
@@ -1,38 +1,33 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<v-container justify="center">
|
|
2
|
+
<v-container justify="center" class="pa-0">
|
|
3
3
|
<v-row justify="center" align="center">
|
|
4
4
|
<v-col cols="12">
|
|
5
5
|
<v-data-table
|
|
6
6
|
:key="tableKey"
|
|
7
7
|
:headers="headers"
|
|
8
8
|
:items="glossaryTerms"
|
|
9
|
+
:footer-props="{
|
|
10
|
+
'items-per-page-options': [5, -1],
|
|
11
|
+
}"
|
|
9
12
|
:search="search"
|
|
10
13
|
class="elevation-1"
|
|
11
14
|
>
|
|
12
15
|
<template #top>
|
|
13
|
-
<v-toolbar
|
|
16
|
+
<v-toolbar
|
|
17
|
+
v-if="
|
|
18
|
+
$PermissionService.userHasAccessTo(
|
|
19
|
+
'plugin.windward.core.organization.course.glossary',
|
|
20
|
+
'writable'
|
|
21
|
+
)
|
|
22
|
+
"
|
|
23
|
+
flat
|
|
24
|
+
>
|
|
14
25
|
<DialogBox
|
|
15
26
|
v-model="dialog"
|
|
16
27
|
color="primary"
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
'windward.global.course,windward.organization.course.contentBlock',
|
|
21
|
-
'writable'
|
|
22
|
-
)
|
|
23
|
-
"
|
|
24
|
-
:action-save-new="
|
|
25
|
-
$PermissionService.userHasAccessTo(
|
|
26
|
-
'windward.global.course,windward.organization.course.contentBlock',
|
|
27
|
-
'writable'
|
|
28
|
-
)
|
|
29
|
-
"
|
|
30
|
-
:action-save="
|
|
31
|
-
$PermissionService.userHasAccessTo(
|
|
32
|
-
'windward.global.course,windward.organization.course.contentBlock',
|
|
33
|
-
'writable'
|
|
34
|
-
)
|
|
35
|
-
"
|
|
28
|
+
trigger
|
|
29
|
+
action-save-new
|
|
30
|
+
action-save
|
|
36
31
|
:disabled="disabled"
|
|
37
32
|
@click:save="save"
|
|
38
33
|
@click:save-new="saveNew"
|
|
@@ -43,9 +38,13 @@
|
|
|
43
38
|
>
|
|
44
39
|
<template #title>
|
|
45
40
|
{{
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
41
|
+
selectedTerm.id
|
|
42
|
+
? $t(
|
|
43
|
+
'windward.core.pages.glossary.edit_term'
|
|
44
|
+
)
|
|
45
|
+
: $t(
|
|
46
|
+
'windward.core.pages.glossary.add_term'
|
|
47
|
+
)
|
|
49
48
|
}}
|
|
50
49
|
</template>
|
|
51
50
|
<template #trigger>
|
|
@@ -53,7 +52,7 @@
|
|
|
53
52
|
{{ $t('shared.forms.add') }}
|
|
54
53
|
</template>
|
|
55
54
|
<template #form="{ on, attrs }">
|
|
56
|
-
<
|
|
55
|
+
<CourseGlossaryForm
|
|
57
56
|
v-model="selectedTerm"
|
|
58
57
|
:glossary="glossaryTerms"
|
|
59
58
|
:edit-mode="editMode"
|
|
@@ -92,16 +91,23 @@
|
|
|
92
91
|
</div>
|
|
93
92
|
</v-row>
|
|
94
93
|
</td>
|
|
95
|
-
<td>
|
|
94
|
+
<td>
|
|
95
|
+
<v-chip
|
|
96
|
+
v-for="related in item.related_terms"
|
|
97
|
+
:key="related.id"
|
|
98
|
+
>
|
|
99
|
+
{{ related.term }}
|
|
100
|
+
</v-chip>
|
|
101
|
+
</td>
|
|
96
102
|
|
|
97
103
|
<td
|
|
98
104
|
v-if="
|
|
99
105
|
$PermissionService.userHasAccessTo(
|
|
100
|
-
'
|
|
106
|
+
'plugin.windward.core.organization.course.glossary',
|
|
101
107
|
'writable'
|
|
102
|
-
)
|
|
108
|
+
) ||
|
|
103
109
|
$PermissionService.userHasAccessTo(
|
|
104
|
-
'
|
|
110
|
+
'plugin.windward.core.organization.course.glossary',
|
|
105
111
|
'deletable'
|
|
106
112
|
)
|
|
107
113
|
"
|
|
@@ -112,16 +118,16 @@
|
|
|
112
118
|
:disabled="disabled"
|
|
113
119
|
>
|
|
114
120
|
<v-btn
|
|
121
|
+
v-if="
|
|
122
|
+
$PermissionService.userHasAccessTo(
|
|
123
|
+
'plugin.windward.core.organization.course.glossary',
|
|
124
|
+
'deletable'
|
|
125
|
+
)
|
|
126
|
+
"
|
|
115
127
|
color="error"
|
|
116
128
|
class="outlined"
|
|
117
129
|
elevation="0"
|
|
118
130
|
outlined
|
|
119
|
-
:disabled="
|
|
120
|
-
!$PermissionService.userHasAccessTo(
|
|
121
|
-
'windward.global.course,windward.organization.course.contentBlock',
|
|
122
|
-
'writable'
|
|
123
|
-
)
|
|
124
|
-
"
|
|
125
131
|
@click="onDelete(item)"
|
|
126
132
|
>
|
|
127
133
|
{{ $t('shared.forms.delete') }}
|
|
@@ -130,16 +136,16 @@
|
|
|
130
136
|
}}</span>
|
|
131
137
|
</v-btn>
|
|
132
138
|
<v-btn
|
|
139
|
+
v-if="
|
|
140
|
+
$PermissionService.userHasAccessTo(
|
|
141
|
+
'plugin.windward.core.organization.course.glossary',
|
|
142
|
+
'writable'
|
|
143
|
+
)
|
|
144
|
+
"
|
|
133
145
|
color="primary"
|
|
134
146
|
class="outlined"
|
|
135
147
|
elevation="0"
|
|
136
148
|
outlined
|
|
137
|
-
:disabled="
|
|
138
|
-
!$PermissionService.userHasAccessTo(
|
|
139
|
-
'windward.global.course,windward.organization.course.contentBlock',
|
|
140
|
-
'writable'
|
|
141
|
-
)
|
|
142
|
-
"
|
|
143
149
|
@click="editTerm(item)"
|
|
144
150
|
>
|
|
145
151
|
{{ $t('shared.forms.edit') }}
|
|
@@ -158,19 +164,18 @@
|
|
|
158
164
|
</template>
|
|
159
165
|
|
|
160
166
|
<script>
|
|
161
|
-
import { mapGetters, mapMutations } from 'vuex'
|
|
167
|
+
import { mapGetters, mapMutations, mapActions } from 'vuex'
|
|
162
168
|
import _ from 'lodash'
|
|
163
|
-
import
|
|
169
|
+
import CourseGlossaryTerm from '../../../models/CourseGlossaryTerm'
|
|
164
170
|
import CourseGlossaryForm from './CourseGlossaryForm'
|
|
165
171
|
import DialogBox from '~/components/Core/DialogBox.vue'
|
|
166
172
|
import Crypto from '~/helpers/Crypto'
|
|
167
173
|
import Course from '~/models/Course'
|
|
168
174
|
import SpeedDial from '~/components/Core/SpeedDial.vue'
|
|
169
|
-
import TextViewer from '~/components/Text/TextViewer.vue'
|
|
170
175
|
|
|
171
176
|
export default {
|
|
172
177
|
name: 'CourseGlossary',
|
|
173
|
-
components: { DialogBox, CourseGlossaryForm, SpeedDial
|
|
178
|
+
components: { DialogBox, CourseGlossaryForm, SpeedDial },
|
|
174
179
|
layout: 'course',
|
|
175
180
|
middleware: ['auth'],
|
|
176
181
|
props: {
|
|
@@ -180,22 +185,21 @@ export default {
|
|
|
180
185
|
return {
|
|
181
186
|
dialog: false,
|
|
182
187
|
editMode: false,
|
|
183
|
-
glossaryTerms: [],
|
|
184
188
|
selectedTerm: {},
|
|
185
189
|
search: '',
|
|
186
190
|
tableKey: Crypto.id(),
|
|
187
191
|
defaultTerm: {
|
|
188
192
|
term: '',
|
|
189
193
|
definition: '',
|
|
190
|
-
alternate_forms:
|
|
191
|
-
|
|
194
|
+
alternate_forms: [],
|
|
195
|
+
related_terms: [],
|
|
192
196
|
},
|
|
193
197
|
}
|
|
194
198
|
},
|
|
195
|
-
|
|
196
199
|
computed: {
|
|
197
200
|
...mapGetters({
|
|
198
201
|
course: 'course/get',
|
|
202
|
+
glossaryTerms: 'glossary/getTerms',
|
|
199
203
|
}),
|
|
200
204
|
...mapMutations({
|
|
201
205
|
saveCourse: 'course/set',
|
|
@@ -223,19 +227,19 @@ export default {
|
|
|
223
227
|
value: 'alternate_forms',
|
|
224
228
|
},
|
|
225
229
|
{
|
|
226
|
-
text: this.$t('windward.core.pages.glossary.
|
|
230
|
+
text: this.$t('windward.core.pages.glossary.related_terms'),
|
|
227
231
|
align: 'start',
|
|
228
232
|
sortable: true,
|
|
229
|
-
value: '
|
|
233
|
+
value: 'related_terms',
|
|
230
234
|
},
|
|
231
235
|
]
|
|
232
236
|
if (
|
|
233
237
|
this.$PermissionService.userHasAccessTo(
|
|
234
|
-
'
|
|
238
|
+
'plugin.windward.core.organization.course.glossary',
|
|
235
239
|
'writable'
|
|
236
|
-
)
|
|
240
|
+
) ||
|
|
237
241
|
this.$PermissionService.userHasAccessTo(
|
|
238
|
-
'
|
|
242
|
+
'plugin.windward.core.organization.course.glossary',
|
|
239
243
|
'deletable'
|
|
240
244
|
)
|
|
241
245
|
) {
|
|
@@ -248,40 +252,19 @@ export default {
|
|
|
248
252
|
return headers
|
|
249
253
|
},
|
|
250
254
|
},
|
|
251
|
-
|
|
252
|
-
beforeMount() {
|
|
253
|
-
if (this.course.metadata && _.isArray(this.course.metadata.glossary)) {
|
|
254
|
-
this.glossaryTerms = _.cloneDeep(this.course.metadata.glossary)
|
|
255
|
-
}
|
|
256
|
-
},
|
|
257
255
|
methods: {
|
|
256
|
+
...mapActions({
|
|
257
|
+
reloadGlossary: 'glossary/load',
|
|
258
|
+
}),
|
|
258
259
|
async save() {
|
|
259
|
-
|
|
260
|
-
this.
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
if (currentGlossaryItemIndex > -1) {
|
|
267
|
-
this.glossaryTerms[currentGlossaryItemIndex] = this.selectedTerm
|
|
268
|
-
} else {
|
|
269
|
-
this.glossaryTerms.push(this.selectedTerm)
|
|
270
|
-
}
|
|
271
|
-
const course = new Course(_.cloneDeep(this.course))
|
|
272
|
-
if (
|
|
273
|
-
!course.hasOwnProperty('metadata') ||
|
|
274
|
-
course.metadata === null
|
|
275
|
-
) {
|
|
276
|
-
course.metadata = {}
|
|
277
|
-
course.metadata.glossary = {}
|
|
278
|
-
}
|
|
260
|
+
// Save the term
|
|
261
|
+
await new CourseGlossaryTerm(_.cloneDeep(this.selectedTerm))
|
|
262
|
+
.for(new Course(this.course))
|
|
263
|
+
.save()
|
|
264
|
+
|
|
265
|
+
// And update our local list
|
|
266
|
+
this.reloadGlossary(this.course)
|
|
279
267
|
|
|
280
|
-
if (course.metadata.glossary !== undefined) {
|
|
281
|
-
course.metadata.glossary = this.glossaryTerms
|
|
282
|
-
}
|
|
283
|
-
const updatedCourse = await course.save()
|
|
284
|
-
this.$store.commit('course/set', updatedCourse)
|
|
285
268
|
this.$toast.success(this.$t('shared.forms.saved'))
|
|
286
269
|
// force update on datatable
|
|
287
270
|
this.tableKey = Crypto.id()
|
|
@@ -327,16 +310,13 @@ export default {
|
|
|
327
310
|
})
|
|
328
311
|
},
|
|
329
312
|
async deleteTerm(item) {
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
course.metadata.glossary = this.glossaryTerms
|
|
338
|
-
const updatedCourse = await course.save()
|
|
339
|
-
this.$store.commit('course/set', updatedCourse)
|
|
313
|
+
// Delete the term
|
|
314
|
+
await new CourseGlossaryTerm(_.cloneDeep(item))
|
|
315
|
+
.for(new Course(this.course))
|
|
316
|
+
.delete()
|
|
317
|
+
|
|
318
|
+
// And update our local list
|
|
319
|
+
this.reloadGlossary(this.course)
|
|
340
320
|
this.$toast.success(this.$t('shared.response.deleted'))
|
|
341
321
|
},
|
|
342
322
|
close() {
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
:label="$t('windward.core.pages.glossary.term')"
|
|
8
8
|
required
|
|
9
9
|
:rules="validation.termRules"
|
|
10
|
-
:disabled="editMode"
|
|
10
|
+
:disabled="editMode || disabled"
|
|
11
11
|
></v-text-field>
|
|
12
12
|
<br />
|
|
13
13
|
<v-textarea
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
outlined
|
|
17
17
|
required
|
|
18
18
|
:rules="validation.definitionRules"
|
|
19
|
+
:disabled="disabled"
|
|
19
20
|
></v-textarea>
|
|
20
21
|
<br />
|
|
21
22
|
<v-combobox
|
|
@@ -25,12 +26,14 @@
|
|
|
25
26
|
:label="$t('windward.core.pages.glossary.alternate_forms')"
|
|
26
27
|
multiple
|
|
27
28
|
solo
|
|
29
|
+
:disabled="disabled"
|
|
28
30
|
>
|
|
29
|
-
<template
|
|
31
|
+
<template #selection="{ attrs, item, select, selected }">
|
|
30
32
|
<v-chip
|
|
31
33
|
v-bind="attrs"
|
|
32
34
|
:input-value="selected"
|
|
33
35
|
close
|
|
36
|
+
:disabled="disabled"
|
|
34
37
|
@click:close="removeAlternateForm(item)"
|
|
35
38
|
>
|
|
36
39
|
<strong>{{ item }}</strong>
|
|
@@ -38,17 +41,22 @@
|
|
|
38
41
|
</template>
|
|
39
42
|
</v-combobox>
|
|
40
43
|
<br />
|
|
41
|
-
<v-
|
|
42
|
-
v-model="selectedTerm.
|
|
44
|
+
<v-autocomplete
|
|
45
|
+
v-model="selectedTerm.related_terms"
|
|
43
46
|
:items="termList"
|
|
47
|
+
item-text="term"
|
|
48
|
+
return-object
|
|
44
49
|
outlined
|
|
45
50
|
clearable
|
|
46
|
-
|
|
47
|
-
|
|
51
|
+
multiple
|
|
52
|
+
:disabled="disabled"
|
|
53
|
+
:label="$t('windward.core.pages.glossary.related_terms')"
|
|
54
|
+
></v-autocomplete>
|
|
48
55
|
</v-form>
|
|
49
56
|
</template>
|
|
50
57
|
|
|
51
58
|
<script>
|
|
59
|
+
import _ from 'lodash'
|
|
52
60
|
import Form from '~/components/Core/Form'
|
|
53
61
|
export default {
|
|
54
62
|
name: 'CourseGlossaryForm',
|
|
@@ -57,17 +65,23 @@ export default {
|
|
|
57
65
|
value: { type: Object, required: true },
|
|
58
66
|
glossary: { type: Array, required: true },
|
|
59
67
|
editMode: { type: Boolean, required: false, default: false },
|
|
68
|
+
disabled: { type: Boolean, required: false, default: false },
|
|
60
69
|
},
|
|
61
70
|
data() {
|
|
62
71
|
return {
|
|
63
|
-
selectedTerm: {
|
|
72
|
+
selectedTerm: {
|
|
73
|
+
term: '',
|
|
74
|
+
definition: '',
|
|
75
|
+
alternate_forms: [],
|
|
76
|
+
related_terms: [],
|
|
77
|
+
},
|
|
64
78
|
relatedTerm: [],
|
|
65
79
|
validation: {
|
|
66
80
|
termRules: [
|
|
67
81
|
(v) => !!v || this.$t('shared.forms.errors.required'),
|
|
68
82
|
(v) =>
|
|
69
83
|
(v && v.length <= 50) ||
|
|
70
|
-
this.$t('forms.errors.text_lt', [50]),
|
|
84
|
+
this.$t('shared.forms.errors.text_lt', [50]),
|
|
71
85
|
(v) =>
|
|
72
86
|
(v && this.termIsUnique(v)) ||
|
|
73
87
|
this.$t('shared.forms.errors.field_unique'),
|
|
@@ -84,18 +98,33 @@ export default {
|
|
|
84
98
|
computed: {
|
|
85
99
|
termList() {
|
|
86
100
|
return this.glossary.flatMap((item) => {
|
|
87
|
-
if (this.selectedTerm.term !== item.term) return item
|
|
101
|
+
if (this.selectedTerm.term !== item.term) return item
|
|
88
102
|
})
|
|
89
103
|
},
|
|
90
104
|
},
|
|
91
105
|
watch: {
|
|
92
|
-
value
|
|
93
|
-
|
|
94
|
-
|
|
106
|
+
value: {
|
|
107
|
+
deep: true,
|
|
108
|
+
handler(newValue) {
|
|
109
|
+
// Refresh the question model when we open / close the dialog
|
|
110
|
+
this.selectedTerm = _.merge(
|
|
111
|
+
this.selectedTerm,
|
|
112
|
+
_.cloneDeep(newValue)
|
|
113
|
+
)
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
selectedTerm: {
|
|
117
|
+
deep: true,
|
|
118
|
+
handler(newValue) {
|
|
119
|
+
if (!_.isEqual(newValue, this.value)) {
|
|
120
|
+
this.$emit('input', newValue)
|
|
121
|
+
}
|
|
122
|
+
},
|
|
95
123
|
},
|
|
96
124
|
},
|
|
97
125
|
mounted() {
|
|
98
|
-
|
|
126
|
+
// Merge to preserve keys in case the value is an empty object for new glossary terms
|
|
127
|
+
this.selectedTerm = _.merge(this.selectedTerm, _.cloneDeep(this.value))
|
|
99
128
|
},
|
|
100
129
|
methods: {
|
|
101
130
|
termIsUnique(term) {
|
|
@@ -8,11 +8,7 @@
|
|
|
8
8
|
:z-index="20"
|
|
9
9
|
>
|
|
10
10
|
<template #activator="{ on }">
|
|
11
|
-
<span
|
|
12
|
-
tabindex="0"
|
|
13
|
-
v-on="on"
|
|
14
|
-
@click.stop="show = !show"
|
|
15
|
-
>
|
|
11
|
+
<span tabindex="0" v-on="on" @click.stop="show = !show">
|
|
16
12
|
<slot name="term"></slot>
|
|
17
13
|
</span>
|
|
18
14
|
</template>
|
|
@@ -34,7 +30,7 @@
|
|
|
34
30
|
</p>
|
|
35
31
|
</div>
|
|
36
32
|
<div v-if="$slots['alternate_forms']">
|
|
37
|
-
<
|
|
33
|
+
<h6 class="text-capitalize">
|
|
38
34
|
<slot name="term"></slot>
|
|
39
35
|
{{
|
|
40
36
|
$t(
|
|
@@ -42,19 +38,19 @@
|
|
|
42
38
|
)
|
|
43
39
|
}}
|
|
44
40
|
:
|
|
45
|
-
</
|
|
41
|
+
</h6>
|
|
46
42
|
<p><slot name="alternate_forms"></slot></p>
|
|
47
43
|
</div>
|
|
48
44
|
|
|
49
45
|
<div v-if="$slots['related_terms']">
|
|
50
|
-
<
|
|
46
|
+
<h6 class="text-capitalize">
|
|
51
47
|
{{
|
|
52
48
|
$t(
|
|
53
49
|
'windward.core.components.utils.tiny_mce_wrapper.related_terms'
|
|
54
50
|
)
|
|
55
51
|
}}
|
|
56
52
|
:
|
|
57
|
-
</
|
|
53
|
+
</h6>
|
|
58
54
|
<p><slot name="related_terms"></slot></p>
|
|
59
55
|
</div>
|
|
60
56
|
</v-card-text>
|
|
@@ -68,12 +64,12 @@ export default {
|
|
|
68
64
|
name: 'GlossaryToolTip',
|
|
69
65
|
data() {
|
|
70
66
|
return {
|
|
71
|
-
show: false
|
|
67
|
+
show: false,
|
|
72
68
|
}
|
|
73
69
|
},
|
|
74
70
|
beforeDestroy() {
|
|
75
71
|
this.show = false
|
|
76
|
-
}
|
|
72
|
+
},
|
|
77
73
|
}
|
|
78
74
|
</script>
|
|
79
75
|
|
|
@@ -1,28 +1,30 @@
|
|
|
1
1
|
import * as _ from 'lodash'
|
|
2
2
|
import { decode } from 'he'
|
|
3
|
-
import
|
|
3
|
+
import CourseGlossaryTerm from '../models/CourseGlossaryTerm'
|
|
4
4
|
|
|
5
5
|
export default class GlossaryHelper {
|
|
6
6
|
private static glossaryRegex =
|
|
7
7
|
/<span.*?.class="glossary-word".*?>(.*?)<\/span>/g
|
|
8
8
|
|
|
9
|
-
public static makeToolTip(term:
|
|
9
|
+
public static makeToolTip(term: CourseGlossaryTerm, text: String): string {
|
|
10
10
|
const word = _.isString(term.term)
|
|
11
11
|
? '<template v-slot:term>' + text + '</template>'
|
|
12
12
|
: ''
|
|
13
13
|
const definition = _.isString(term.definition)
|
|
14
14
|
? '<template v-slot:definition>' + term.definition + '</template>'
|
|
15
15
|
: ''
|
|
16
|
-
const alternate_forms =
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
16
|
+
const alternate_forms =
|
|
17
|
+
_.isArray(term.alternate_forms) && term.alternate_forms.length > 0
|
|
18
|
+
? '<template v-slot:alternate_forms>' +
|
|
19
|
+
term.alternate_forms.join(',') +
|
|
20
|
+
'</template>'
|
|
21
|
+
: ''
|
|
22
|
+
const related_terms =
|
|
23
|
+
_.isArray(term.related_terms) && term.related_terms.length > 0
|
|
24
|
+
? '<template v-slot:related_terms>' +
|
|
25
|
+
term.related_terms.map((t) => t.term).join(',') +
|
|
26
|
+
'</template>'
|
|
27
|
+
: ''
|
|
26
28
|
return (
|
|
27
29
|
'<plugin-core-glossary-tool-tip>' +
|
|
28
30
|
word +
|
|
@@ -47,7 +49,7 @@ export default class GlossaryHelper {
|
|
|
47
49
|
const currentGlossary = glossary
|
|
48
50
|
|
|
49
51
|
let match: any
|
|
50
|
-
const verifiedTerms:
|
|
52
|
+
const verifiedTerms: CourseGlossaryTerm[] = []
|
|
51
53
|
while ((match = regex.exec(content)) !== null) {
|
|
52
54
|
// This is necessary to avoid infinite loops with zero-width matches
|
|
53
55
|
if (match.index === regex.lastIndex) {
|
|
@@ -78,7 +80,7 @@ export default class GlossaryHelper {
|
|
|
78
80
|
))) &&
|
|
79
81
|
addTerm
|
|
80
82
|
) {
|
|
81
|
-
verifiedTerms.push(new
|
|
83
|
+
verifiedTerms.push(new CourseGlossaryTerm(term))
|
|
82
84
|
}
|
|
83
85
|
})
|
|
84
86
|
}
|
|
@@ -97,7 +99,7 @@ export default class GlossaryHelper {
|
|
|
97
99
|
content,
|
|
98
100
|
glossary
|
|
99
101
|
)
|
|
100
|
-
const unVerifiedTerms:
|
|
102
|
+
const unVerifiedTerms: CourseGlossaryTerm[] = []
|
|
101
103
|
while ((match = regex.exec(content)) !== null) {
|
|
102
104
|
// This is necessary to avoid infinite loops with zero-width matches
|
|
103
105
|
if (match.index === regex.lastIndex) {
|
|
@@ -134,7 +136,7 @@ export default class GlossaryHelper {
|
|
|
134
136
|
})
|
|
135
137
|
if (inGlossary.length === 0 && !inUnverifiedArray) {
|
|
136
138
|
unVerifiedTerms.push(
|
|
137
|
-
new
|
|
139
|
+
new CourseGlossaryTerm({
|
|
138
140
|
term: _.trim(match[1]),
|
|
139
141
|
definition: 'n/a',
|
|
140
142
|
})
|
|
@@ -1,20 +1,35 @@
|
|
|
1
1
|
export default {
|
|
2
2
|
error: {
|
|
3
3
|
default: 'Could not generate question from provided content.',
|
|
4
|
-
default_support:
|
|
5
|
-
|
|
4
|
+
default_support:
|
|
5
|
+
'Please try again or contact support if the issue persists.',
|
|
6
|
+
|
|
6
7
|
insufficient_content: 'More content needed to generate questions.',
|
|
7
|
-
insufficient_content_support:
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
insufficient_content_support:
|
|
9
|
+
'Please add more text, examples, or explanations to this section. We recommend at least 50 words of relevant content to generate appropriate questions.',
|
|
10
|
+
|
|
11
|
+
content_mismatch: "Content doesn't match question type.",
|
|
12
|
+
content_mismatch_support:
|
|
13
|
+
"The current content isn't suitable for this type of question. Consider adding more specific examples, numerical data, or comparable items depending on your desired question type.",
|
|
14
|
+
|
|
12
15
|
llm_unavailable: 'Question generation temporarily unavailable.',
|
|
13
|
-
llm_unavailable_support:
|
|
14
|
-
|
|
16
|
+
llm_unavailable_support:
|
|
17
|
+
"We're unable to connect to our AI service at the moment. Please try again in a few minutes or contact support if the issue persists.",
|
|
18
|
+
|
|
15
19
|
technical: 'Unable to process request.',
|
|
16
|
-
technical_support:
|
|
20
|
+
technical_support:
|
|
21
|
+
'Something went wrong on our end. Please try again or contact support if this continues. Reference code: [ERROR_CODE]',
|
|
17
22
|
},
|
|
18
23
|
button_label: 'Generate Question',
|
|
19
|
-
selected_pages: 'Selected Page'
|
|
24
|
+
selected_pages: 'Selected Page',
|
|
25
|
+
ai_assistance: 'AI Assistance',
|
|
26
|
+
blooms: {
|
|
27
|
+
blooms_taxonomy: "Bloom's Taxonomy Level",
|
|
28
|
+
none: 'None selected',
|
|
29
|
+
remember: 'Remember',
|
|
30
|
+
understand: 'Understand',
|
|
31
|
+
apply: 'Apply',
|
|
32
|
+
analyze: 'Analyze',
|
|
33
|
+
evaluate: 'Evaluate',
|
|
34
|
+
},
|
|
20
35
|
}
|
|
@@ -8,7 +8,7 @@ export default {
|
|
|
8
8
|
math: 'Math',
|
|
9
9
|
accordion: 'Accordion',
|
|
10
10
|
open_response: 'Open Response',
|
|
11
|
-
open_response_collate: 'Open Response
|
|
11
|
+
open_response_collate: 'Open Response Download',
|
|
12
12
|
image: 'Image',
|
|
13
13
|
user_upload: 'User Upload',
|
|
14
14
|
clickable_icons: 'Clickable Icons',
|
|
@@ -9,5 +9,10 @@ export default {
|
|
|
9
9
|
'windward-core-ask-the-expert': 'Course Ask the Expert',
|
|
10
10
|
'windward-core-contact-support': 'Course Contact Support',
|
|
11
11
|
},
|
|
12
|
+
|
|
13
|
+
type_recipient_address: {
|
|
14
|
+
'windward-core-ask-the-expert': '{{courseowner->email}}',
|
|
15
|
+
'windward-core-contact-support': '',
|
|
16
|
+
},
|
|
12
17
|
},
|
|
13
18
|
}
|
|
@@ -4,6 +4,8 @@ export default {
|
|
|
4
4
|
'Feedback access for the current user',
|
|
5
5
|
'plugin->windward->core->organization->course->user->userUpload':
|
|
6
6
|
'User upload block access for the current user',
|
|
7
|
+
'plugin->windward->core->organization->course->glossary':
|
|
8
|
+
'Course Glossary',
|
|
7
9
|
},
|
|
8
10
|
|
|
9
11
|
type_description: {
|
|
@@ -11,5 +13,7 @@ export default {
|
|
|
11
13
|
'The current users access to the feedback block',
|
|
12
14
|
'plugin->windward->core->organization->course->user->userUpload':
|
|
13
15
|
'The current users access to the user upload block',
|
|
16
|
+
'plugin->windward->core->organization->course->glossary':
|
|
17
|
+
'Access and manage the course glossary in the current organization for your own courses',
|
|
14
18
|
},
|
|
15
19
|
}
|