@windward/integrations 0.0.5 → 0.0.7
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/components/Content/Blocks/ExternalIntegration/LtiConsumer.vue +205 -0
- package/components/ExternalIntegration/Driver/Lti1p1/ManageConsumer.vue +284 -3
- package/components/ExternalIntegration/Driver/Lti1p1/ManageConsumers.vue +199 -3
- package/components/ExternalIntegration/Driver/Lti1p1/ManageProvider.vue +36 -6
- package/components/ExternalIntegration/Driver/Lti1p1/ManageProviders.vue +36 -17
- package/components/ExternalIntegration/Driver/ManageLti1p1.vue +5 -5
- package/components/ExternalIntegration/ProviderTargetPicker.vue +234 -0
- package/components/ExternalIntegration/ProviderTargetViewer.vue +50 -0
- package/components/Integration/Driver/ManageBase.vue +3 -1
- package/components/Integration/JobTable.vue +2 -1
- package/components/SecretField.vue +1 -1
- package/components/Settings/ExternalIntegration/LtiConsumerSettings.vue +105 -0
- package/i18n/en-US/components/content/blocks/external_integration/index.ts +5 -0
- package/i18n/en-US/components/content/blocks/external_integration/lti_consumer.ts +8 -0
- package/i18n/en-US/components/content/blocks/index.ts +5 -0
- package/i18n/en-US/components/content/index.ts +5 -0
- package/i18n/en-US/components/external_integration/driver/lti1p1.ts +11 -2
- package/i18n/en-US/components/external_integration/index.ts +2 -1
- package/i18n/en-US/components/external_integration/provider_target.ts +9 -0
- package/i18n/en-US/components/index.ts +4 -0
- package/i18n/en-US/components/settings/external_integration/index.ts +5 -0
- package/i18n/en-US/components/settings/external_integration/lti_consumer.ts +7 -0
- package/i18n/en-US/components/settings/index.ts +5 -0
- package/i18n/en-US/shared/content_blocks.ts +8 -0
- package/i18n/en-US/shared/index.ts +2 -0
- package/i18n/en-US/shared/settings.ts +5 -1
- package/package.json +1 -1
- package/pages/admin/importCourse.vue +3 -0
- package/pages/admin/vendors.vue +2 -1
- package/plugin.js +27 -1
- package/test/Components/Content/Blocks/ExternalIntegration/LtiConsumer.spec.js +26 -0
- package/test/Components/ExternalIntegration/ProviderTargetPicker.spec.js +22 -0
- package/test/Components/ExternalIntegration/ProviderTargetViewer.spec.js +22 -0
- package/test/__mocks__/componentsMock.js +12 -0
- package/test/__mocks__/modelMock.js +1 -1
- package/test/mocks.js +1 -0
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
<v-radio-group
|
|
4
|
+
v-model="localMetadata.target_type"
|
|
5
|
+
row
|
|
6
|
+
@change="onTargetTypeChange"
|
|
7
|
+
>
|
|
8
|
+
<template #label>
|
|
9
|
+
<div>
|
|
10
|
+
{{
|
|
11
|
+
$t(
|
|
12
|
+
'windward.integrations.components.external_integration.provider_target.link_to'
|
|
13
|
+
)
|
|
14
|
+
}}:
|
|
15
|
+
</div>
|
|
16
|
+
</template>
|
|
17
|
+
<v-radio
|
|
18
|
+
:label="
|
|
19
|
+
$t(
|
|
20
|
+
'windward.integrations.components.external_integration.provider_target.whole_course'
|
|
21
|
+
)
|
|
22
|
+
"
|
|
23
|
+
value="course"
|
|
24
|
+
></v-radio>
|
|
25
|
+
<v-radio
|
|
26
|
+
:label="
|
|
27
|
+
$t(
|
|
28
|
+
'windward.integrations.components.external_integration.provider_target.content_with_children'
|
|
29
|
+
)
|
|
30
|
+
"
|
|
31
|
+
value="locked_course_content_children"
|
|
32
|
+
></v-radio>
|
|
33
|
+
<v-radio
|
|
34
|
+
:label="
|
|
35
|
+
$t(
|
|
36
|
+
'windward.integrations.components.external_integration.provider_target.content_no_children'
|
|
37
|
+
)
|
|
38
|
+
"
|
|
39
|
+
value="locked_course_content"
|
|
40
|
+
></v-radio>
|
|
41
|
+
<v-radio
|
|
42
|
+
:label="
|
|
43
|
+
$t(
|
|
44
|
+
'windward.integrations.components.external_integration.provider_target.whole_course_page'
|
|
45
|
+
)
|
|
46
|
+
"
|
|
47
|
+
value="course_content"
|
|
48
|
+
></v-radio>
|
|
49
|
+
</v-radio-group>
|
|
50
|
+
|
|
51
|
+
<div
|
|
52
|
+
v-if="
|
|
53
|
+
localMetadata.target_type === 'course_content' ||
|
|
54
|
+
localMetadata.target_type ===
|
|
55
|
+
'locked_course_content_children' ||
|
|
56
|
+
localMetadata.target_type === 'locked_course_content'
|
|
57
|
+
"
|
|
58
|
+
class="content-tree secondary"
|
|
59
|
+
>
|
|
60
|
+
<v-treeview
|
|
61
|
+
v-model="selectedTreeviewContent"
|
|
62
|
+
selectable
|
|
63
|
+
selected-color="primary"
|
|
64
|
+
selection-type="independent"
|
|
65
|
+
return-object
|
|
66
|
+
open-all
|
|
67
|
+
:items="contentTree"
|
|
68
|
+
@input="onTreeChange"
|
|
69
|
+
>
|
|
70
|
+
<template #prepend="{ item }">
|
|
71
|
+
<v-chip v-if="isIncludedChild(item)" color="primary">
|
|
72
|
+
{{
|
|
73
|
+
$t(
|
|
74
|
+
'windward.integrations.components.external_integration.provider_target.included'
|
|
75
|
+
)
|
|
76
|
+
}}
|
|
77
|
+
</v-chip>
|
|
78
|
+
</template>
|
|
79
|
+
<template #label="{ item }">
|
|
80
|
+
{{ item.content.name_prefix }}
|
|
81
|
+
{{ item.content.name }}
|
|
82
|
+
</template>
|
|
83
|
+
</v-treeview>
|
|
84
|
+
</div>
|
|
85
|
+
</div>
|
|
86
|
+
</template>
|
|
87
|
+
|
|
88
|
+
<script>
|
|
89
|
+
import _ from 'lodash'
|
|
90
|
+
import { mapGetters } from 'vuex'
|
|
91
|
+
export default {
|
|
92
|
+
name: 'ExternalIntegrationProviderTargetPicker',
|
|
93
|
+
props: {
|
|
94
|
+
target: { type: String, required: true, default: '' },
|
|
95
|
+
metadata: { type: Object, required: true, default: () => {} },
|
|
96
|
+
},
|
|
97
|
+
data() {
|
|
98
|
+
return {
|
|
99
|
+
selectedContent: null,
|
|
100
|
+
selectedTreeviewContent: [],
|
|
101
|
+
localTarget: '',
|
|
102
|
+
localMetadata: {},
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
computed: {
|
|
106
|
+
...mapGetters({
|
|
107
|
+
contentTree: 'content/getTree',
|
|
108
|
+
course: 'course/get',
|
|
109
|
+
}),
|
|
110
|
+
},
|
|
111
|
+
watch: {
|
|
112
|
+
// Apply any changes coming up
|
|
113
|
+
target: {
|
|
114
|
+
handler(value) {
|
|
115
|
+
this.localTarget = _.cloneDeep(value)
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
metadata: {
|
|
119
|
+
deep: true,
|
|
120
|
+
handler(value) {
|
|
121
|
+
this.localMetadata = _.cloneDeep(value)
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
mounted() {
|
|
126
|
+
// Init our local vars
|
|
127
|
+
this.localTarget = _.cloneDeep(this.target)
|
|
128
|
+
this.localMetadata = _.cloneDeep(this.metadata)
|
|
129
|
+
|
|
130
|
+
// Set the target_type key if it doesn't exist
|
|
131
|
+
if (!this.localMetadata.target_type) {
|
|
132
|
+
this.localMetadata.target_type = ''
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Preset the selected content
|
|
136
|
+
if (this.localTarget) {
|
|
137
|
+
const match = this.localTarget.match(
|
|
138
|
+
/\/content\/(?<content_id>[a-zA-Z0-9-]{36})/i
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
if (!_.isEmpty(match) && _.get(match, 'groups.content_id', null)) {
|
|
142
|
+
this.setSelectedContentById(
|
|
143
|
+
_.get(match, 'groups.content_id', null)
|
|
144
|
+
)
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
this.sync(this.localMetadata.target_type)
|
|
148
|
+
},
|
|
149
|
+
methods: {
|
|
150
|
+
setSelectedContentById(id) {
|
|
151
|
+
this.selectedContent = { id }
|
|
152
|
+
this.selectedTreeviewContent = [{ id }]
|
|
153
|
+
},
|
|
154
|
+
sync(targetType) {
|
|
155
|
+
let url = ''
|
|
156
|
+
|
|
157
|
+
if (
|
|
158
|
+
this.selectedContent &&
|
|
159
|
+
(targetType === 'course_content' ||
|
|
160
|
+
targetType === 'locked_course_content' ||
|
|
161
|
+
targetType === 'locked_course_content_children')
|
|
162
|
+
) {
|
|
163
|
+
url = `/course/${this.course.id}/content/${this.selectedContent.id}`
|
|
164
|
+
} else if (targetType === 'course') {
|
|
165
|
+
url = `/course/${this.course.id}/`
|
|
166
|
+
}
|
|
167
|
+
this.localTarget = url
|
|
168
|
+
// Sync up the changes to the parent component
|
|
169
|
+
this.$emit('update:target', this.localTarget)
|
|
170
|
+
this.$emit('update:metadata', this.localMetadata)
|
|
171
|
+
},
|
|
172
|
+
onTargetTypeChange(e) {
|
|
173
|
+
// Reset the selected content if you pick by course
|
|
174
|
+
if (e === 'course') {
|
|
175
|
+
this.selectedContent = null
|
|
176
|
+
this.selectedTreeviewContent = []
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
this.sync(e)
|
|
180
|
+
},
|
|
181
|
+
isIncludedChild(page, children = null) {
|
|
182
|
+
let isIncluded = false
|
|
183
|
+
// If we aren't including children then return hard false
|
|
184
|
+
if (
|
|
185
|
+
this.localMetadata.target_type !==
|
|
186
|
+
'locked_course_content_children'
|
|
187
|
+
) {
|
|
188
|
+
return false
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// First run, assign the children from the selected page
|
|
192
|
+
if (this.selectedContent && children === null) {
|
|
193
|
+
children = _.get(this.selectedContent, 'children', [])
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if (this.selectedContent && page.parent_id) {
|
|
197
|
+
if (this.selectedContent.id === page.parent_id) {
|
|
198
|
+
return true
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
for (let i = 0; i < children.length; i++) {
|
|
202
|
+
const child = children[i]
|
|
203
|
+
|
|
204
|
+
if (child.id === page.parent_id) {
|
|
205
|
+
return true
|
|
206
|
+
} else if (child.children && child.children.length) {
|
|
207
|
+
isIncluded = this.isIncludedChild(page, child.children)
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
return isIncluded
|
|
212
|
+
},
|
|
213
|
+
onTreeChange() {
|
|
214
|
+
// Enforce that only 1 item is selected at a time in the treeview
|
|
215
|
+
if (this.selectedTreeviewContent.length > 0) {
|
|
216
|
+
const last = this.selectedTreeviewContent.pop()
|
|
217
|
+
this.selectedTreeviewContent = [last]
|
|
218
|
+
this.selectedContent = last
|
|
219
|
+
} else {
|
|
220
|
+
this.selectedContent = null
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
this.sync(this.localMetadata.target_type)
|
|
224
|
+
},
|
|
225
|
+
},
|
|
226
|
+
}
|
|
227
|
+
</script>
|
|
228
|
+
|
|
229
|
+
<style scoped>
|
|
230
|
+
.content-tree {
|
|
231
|
+
height: 230px;
|
|
232
|
+
overflow-y: auto;
|
|
233
|
+
}
|
|
234
|
+
</style>
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<span>{{ targetDisplayName }}</span>
|
|
3
|
+
</template>
|
|
4
|
+
|
|
5
|
+
<script>
|
|
6
|
+
import _ from 'lodash'
|
|
7
|
+
import { mapGetters } from 'vuex'
|
|
8
|
+
export default {
|
|
9
|
+
name: 'ExternalIntegrationProviderTargetViewer',
|
|
10
|
+
props: {
|
|
11
|
+
target: { type: String, required: true, default: '' },
|
|
12
|
+
},
|
|
13
|
+
computed: {
|
|
14
|
+
...mapGetters({
|
|
15
|
+
organization: 'organization/get',
|
|
16
|
+
course: 'course/get',
|
|
17
|
+
contentTree: 'content/getTree',
|
|
18
|
+
}),
|
|
19
|
+
targetDisplayName() {
|
|
20
|
+
if (_.isEmpty(this.target)) {
|
|
21
|
+
return ''
|
|
22
|
+
}
|
|
23
|
+
const match = this.target.match(
|
|
24
|
+
/\/content\/(?<content_id>[a-zA-Z0-9-]{36})/i
|
|
25
|
+
)
|
|
26
|
+
if (!_.isEmpty(match) && _.get(match, 'groups.content_id', null)) {
|
|
27
|
+
const flatTree = this.$ContentService.flattenTree(
|
|
28
|
+
this.contentTree
|
|
29
|
+
)
|
|
30
|
+
const item = flatTree.find(
|
|
31
|
+
(c) => c.id === _.get(match, 'groups.content_id', null)
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
if (!_.isEmpty(item)) {
|
|
35
|
+
return (
|
|
36
|
+
_.get(item, 'content.name_prefix', '') +
|
|
37
|
+
' ' +
|
|
38
|
+
_.get(item, 'content.name', '')
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
} else {
|
|
42
|
+
return this.$t(
|
|
43
|
+
'windward.integrations.components.external_integration.provider_target.whole_course'
|
|
44
|
+
)
|
|
45
|
+
}
|
|
46
|
+
return ''
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
}
|
|
50
|
+
</script>
|
|
@@ -38,11 +38,12 @@ export default {
|
|
|
38
38
|
duration: null,
|
|
39
39
|
action: {
|
|
40
40
|
text: this.$t('shared.forms.close'),
|
|
41
|
-
onClick: (
|
|
41
|
+
onClick: (_e, toastObject) => {
|
|
42
42
|
toastObject.goAway(0)
|
|
43
43
|
},
|
|
44
44
|
},
|
|
45
45
|
})
|
|
46
|
+
// eslint-disable-next-line no-console
|
|
46
47
|
console.error('You do not have access to this integration!')
|
|
47
48
|
|
|
48
49
|
// Return so we don't even attempt loading
|
|
@@ -129,6 +130,7 @@ export default {
|
|
|
129
130
|
},
|
|
130
131
|
|
|
131
132
|
onIntegrationLoaded() {
|
|
133
|
+
// eslint-disable-next-line no-console
|
|
132
134
|
console.warn(
|
|
133
135
|
'Integration/Driver/ManageBase.vue onIntegrationLoaded called. Not extended!'
|
|
134
136
|
)
|
|
@@ -247,7 +247,7 @@ export default {
|
|
|
247
247
|
connect(channel, event) {
|
|
248
248
|
this.socket.connector.pusher.connection.bind(
|
|
249
249
|
'connected',
|
|
250
|
-
function (
|
|
250
|
+
function (_socket) {
|
|
251
251
|
// Connected to socket id: socket.socket_id
|
|
252
252
|
}
|
|
253
253
|
)
|
|
@@ -266,6 +266,7 @@ export default {
|
|
|
266
266
|
|
|
267
267
|
onSocketJob(data) {
|
|
268
268
|
if (_.isEmpty(data.integrationJob)) {
|
|
269
|
+
// eslint-disable-next-line no-console
|
|
269
270
|
console.error('onSocketJob Missing data', data)
|
|
270
271
|
return false
|
|
271
272
|
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-container>
|
|
3
|
+
<v-select
|
|
4
|
+
v-model="block.metadata.config.launch_type"
|
|
5
|
+
:label="
|
|
6
|
+
$t(
|
|
7
|
+
'windward.integrations.components.settings.external_integration.lti_consumer.launch_type'
|
|
8
|
+
)
|
|
9
|
+
"
|
|
10
|
+
:items="launchTypes"
|
|
11
|
+
item-text="name"
|
|
12
|
+
item-value="value"
|
|
13
|
+
></v-select>
|
|
14
|
+
{{
|
|
15
|
+
$t(
|
|
16
|
+
'windward.integrations.components.settings.external_integration.lti_consumer.link_select'
|
|
17
|
+
)
|
|
18
|
+
}}
|
|
19
|
+
<v-list>
|
|
20
|
+
<v-list-item
|
|
21
|
+
v-for="consumer in consumers"
|
|
22
|
+
:key="consumer.id"
|
|
23
|
+
two-line
|
|
24
|
+
:disabled="!consumer.enabled"
|
|
25
|
+
@click="onSelectLink(consumer)"
|
|
26
|
+
>
|
|
27
|
+
<v-list-item-avatar :color="!consumer.enabled ? 'error' : ''">
|
|
28
|
+
<v-icon> mdi-shield-link-variant-outline </v-icon>
|
|
29
|
+
</v-list-item-avatar>
|
|
30
|
+
<v-list-item-content>
|
|
31
|
+
<v-list-item-title>{{ consumer.name }}</v-list-item-title>
|
|
32
|
+
<v-list-item-subtitle v-if="!consumer.enabled">
|
|
33
|
+
<v-chip color="error">{{
|
|
34
|
+
$t(
|
|
35
|
+
'windward.integrations.components.settings.external_integration.lti_consumer.link_disabled'
|
|
36
|
+
)
|
|
37
|
+
}}</v-chip>
|
|
38
|
+
</v-list-item-subtitle>
|
|
39
|
+
<v-list-item-subtitle>{{
|
|
40
|
+
consumer.description.replace(/(<([^>]+)>)/gi, '').trim()
|
|
41
|
+
}}</v-list-item-subtitle>
|
|
42
|
+
</v-list-item-content>
|
|
43
|
+
</v-list-item>
|
|
44
|
+
</v-list>
|
|
45
|
+
</v-container>
|
|
46
|
+
</template>
|
|
47
|
+
|
|
48
|
+
<script>
|
|
49
|
+
import { mapGetters } from 'vuex'
|
|
50
|
+
import BaseContentSettings from '~/components/Content/Tool/BaseContentSettings.js'
|
|
51
|
+
import Course from '~/models/Course'
|
|
52
|
+
import Organization from '~/models/Organization'
|
|
53
|
+
import Lti1p1Consumer from '../../../models/ExternalIntegration/Lti1p1Consumer'
|
|
54
|
+
|
|
55
|
+
export default {
|
|
56
|
+
name: 'ContentBlockExternalIntegrationLti1p1ConsumerSettings',
|
|
57
|
+
extends: BaseContentSettings,
|
|
58
|
+
props: {
|
|
59
|
+
settings: { type: Object, required: false, default: null },
|
|
60
|
+
context: { type: String, required: false, default: 'block' },
|
|
61
|
+
},
|
|
62
|
+
data() {
|
|
63
|
+
return {
|
|
64
|
+
consumers: [],
|
|
65
|
+
launchTypes: [
|
|
66
|
+
{
|
|
67
|
+
name: this.$t(
|
|
68
|
+
'windward.integrations.components.settings.external_integration.lti_consumer.launch_type_new_window'
|
|
69
|
+
),
|
|
70
|
+
value: 'new_window',
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
name: this.$t(
|
|
74
|
+
'windward.integrations.components.settings.external_integration.lti_consumer.launch_type_inline_frame'
|
|
75
|
+
),
|
|
76
|
+
value: 'inline',
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
async fetch() {
|
|
82
|
+
this.consumers = await new Lti1p1Consumer()
|
|
83
|
+
.for(
|
|
84
|
+
new Organization({ id: this.organization.id }),
|
|
85
|
+
new Course({ id: this.course.id })
|
|
86
|
+
)
|
|
87
|
+
.orderBy('name')
|
|
88
|
+
.get()
|
|
89
|
+
},
|
|
90
|
+
computed: {
|
|
91
|
+
...mapGetters({
|
|
92
|
+
organization: 'organization/get',
|
|
93
|
+
course: 'course/get',
|
|
94
|
+
}),
|
|
95
|
+
},
|
|
96
|
+
watch: {},
|
|
97
|
+
beforeMount() {},
|
|
98
|
+
mounted() {},
|
|
99
|
+
methods: {
|
|
100
|
+
onSelectLink(consumer) {
|
|
101
|
+
this.block.metadata.config.tool_id = consumer.id
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
}
|
|
105
|
+
</script>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
launch: 'Launch',
|
|
3
|
+
configure_warning:
|
|
4
|
+
'This block needs to be configured. Please select a LTI tool in the settings panel.',
|
|
5
|
+
missing_tool: 'The tool id {0} is missing',
|
|
6
|
+
unknown_error: 'Something went wrong! Could not launch this link!',
|
|
7
|
+
link_disabled: 'Link disabled',
|
|
8
|
+
}
|
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
export default {
|
|
2
|
+
name: 'Name',
|
|
3
|
+
description: 'Description',
|
|
2
4
|
key: 'Key',
|
|
3
5
|
secret: 'Secret',
|
|
4
|
-
|
|
5
|
-
|
|
6
|
+
parameter_name: 'Custom Parameter Name',
|
|
7
|
+
value: 'Value',
|
|
8
|
+
auto_key: 'Leave empty for autogenerated key',
|
|
9
|
+
auto_secret: 'Leave empty for autogenerated secret',
|
|
10
|
+
change_key: 'Change Key',
|
|
11
|
+
change_secret: 'Change Secret',
|
|
12
|
+
new_key: 'New Key',
|
|
13
|
+
new_secret: 'New Secret',
|
|
14
|
+
target: 'Target',
|
|
6
15
|
target_url: 'Target Url',
|
|
7
16
|
launch_url: 'Launch Url',
|
|
8
17
|
new: 'New LTI Link',
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
name: 'Target Name',
|
|
3
|
+
link_to: 'Link To',
|
|
4
|
+
included: 'Included',
|
|
5
|
+
whole_course: 'Whole Course',
|
|
6
|
+
whole_course_page: 'Whole Course Choose Landing Page',
|
|
7
|
+
content_with_children: 'Content with Child Pages',
|
|
8
|
+
content_no_children: 'Single Content Page',
|
|
9
|
+
}
|
|
@@ -1,8 +1,12 @@
|
|
|
1
|
+
import content from './content'
|
|
2
|
+
import settings from './settings'
|
|
1
3
|
import navigation from './navigation'
|
|
2
4
|
import integration from './integration'
|
|
3
5
|
import externalIntegration from './external_integration'
|
|
4
6
|
|
|
5
7
|
export default {
|
|
8
|
+
content,
|
|
9
|
+
settings,
|
|
6
10
|
navigation,
|
|
7
11
|
integration,
|
|
8
12
|
external_integration: externalIntegration,
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import contentBlocks from './content_blocks'
|
|
1
2
|
import settings from './settings'
|
|
2
3
|
import menu from './menu'
|
|
3
4
|
import permission from './permission'
|
|
4
5
|
import error from './error'
|
|
5
6
|
|
|
6
7
|
export default {
|
|
8
|
+
content_blocks: contentBlocks,
|
|
7
9
|
settings,
|
|
8
10
|
menu,
|
|
9
11
|
permission,
|
package/package.json
CHANGED
|
@@ -287,6 +287,7 @@ export default {
|
|
|
287
287
|
.get()
|
|
288
288
|
} catch (e) {
|
|
289
289
|
if (e.response.status === 404) {
|
|
290
|
+
// eslint-disable-next-line no-console
|
|
290
291
|
console.error(e)
|
|
291
292
|
this.$dialog.error(
|
|
292
293
|
this.$t(
|
|
@@ -329,6 +330,7 @@ export default {
|
|
|
329
330
|
.get()
|
|
330
331
|
} catch (e) {
|
|
331
332
|
if (e.response.status === 404) {
|
|
333
|
+
// eslint-disable-next-line no-console
|
|
332
334
|
console.error(e)
|
|
333
335
|
this.$dialog.error(
|
|
334
336
|
this.$t(
|
|
@@ -374,6 +376,7 @@ export default {
|
|
|
374
376
|
}
|
|
375
377
|
} catch (e) {
|
|
376
378
|
if (e.response.status === 404) {
|
|
379
|
+
// eslint-disable-next-line no-console
|
|
377
380
|
console.error(e)
|
|
378
381
|
this.$dialog.error(
|
|
379
382
|
this.$t(
|
package/pages/admin/vendors.vue
CHANGED
|
@@ -151,9 +151,9 @@
|
|
|
151
151
|
import _ from 'lodash'
|
|
152
152
|
import { mapGetters } from 'vuex'
|
|
153
153
|
|
|
154
|
+
import Dialog from '~/components/Dialog.vue'
|
|
154
155
|
import Organization from '../../models/Organization'
|
|
155
156
|
import IntegrationJobTable from '../../components/Integration/JobTable.vue'
|
|
156
|
-
import Dialog from '~/components/Dialog.vue'
|
|
157
157
|
|
|
158
158
|
export default {
|
|
159
159
|
name: 'PluginIntegrationsAdminVendorsPage',
|
|
@@ -216,6 +216,7 @@ export default {
|
|
|
216
216
|
.integrations()
|
|
217
217
|
.get()
|
|
218
218
|
} catch (e) {
|
|
219
|
+
// eslint-disable-next-line no-console
|
|
219
220
|
console.error('Could not load organization integrations', e)
|
|
220
221
|
}
|
|
221
222
|
},
|
package/plugin.js
CHANGED
|
@@ -6,6 +6,9 @@ import ExternalIntegrationIndexPage from './pages/course/externalIntegration/ind
|
|
|
6
6
|
import LoginLtiErrorPage from './pages/login/lti/error.vue'
|
|
7
7
|
import IntegrationHelper from './helpers/IntegrationHelper'
|
|
8
8
|
|
|
9
|
+
import LtiConsumerBlock from './components/Content/Blocks/ExternalIntegration/LtiConsumer'
|
|
10
|
+
import LtiConsumerBlockSettings from './components/Settings/ExternalIntegration/LtiConsumerSettings'
|
|
11
|
+
|
|
9
12
|
export default {
|
|
10
13
|
name: 'windward.integrations.name',
|
|
11
14
|
hooks: {
|
|
@@ -15,7 +18,7 @@ export default {
|
|
|
15
18
|
beforeDestroy: () => {},
|
|
16
19
|
beforeNavigate: () => {},
|
|
17
20
|
onNavigate: () => {},
|
|
18
|
-
onLoad: (
|
|
21
|
+
onLoad: (_page) => {},
|
|
19
22
|
onContent: () => {},
|
|
20
23
|
},
|
|
21
24
|
i18n: {
|
|
@@ -131,6 +134,29 @@ export default {
|
|
|
131
134
|
],
|
|
132
135
|
},
|
|
133
136
|
],
|
|
137
|
+
contentBlock: [
|
|
138
|
+
{
|
|
139
|
+
tag: 'windward-integrations-lti-consumer',
|
|
140
|
+
template: LtiConsumerBlock,
|
|
141
|
+
metadata: {
|
|
142
|
+
icon: 'mdi-shield-link-variant-outline',
|
|
143
|
+
name: 'windward.integrations.shared.content_blocks.title.lti_consumer',
|
|
144
|
+
grouping:
|
|
145
|
+
'windward.integrations.shared.content_blocks.grouping.integrations',
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
],
|
|
149
|
+
settings: [
|
|
150
|
+
{
|
|
151
|
+
tag: 'windward-integrations-lti-consumer-settings',
|
|
152
|
+
template: LtiConsumerBlockSettings,
|
|
153
|
+
context: ['block.windward-integrations-lti-consumer'],
|
|
154
|
+
metadata: {
|
|
155
|
+
icon: 'mdi-cog',
|
|
156
|
+
name: 'windward.integrations.shared.settings.title.lti_consumer',
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
],
|
|
134
160
|
},
|
|
135
161
|
services: {
|
|
136
162
|
Integration: IntegrationHelper,
|