@windward/integrations 0.0.2 → 0.0.4
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/ExternalIntegration/Driver/Lti1p1/ManageConsumer.vue +13 -0
- package/components/ExternalIntegration/Driver/Lti1p1/ManageConsumers.vue +13 -0
- package/components/ExternalIntegration/Driver/Lti1p1/ManageProvider.vue +374 -0
- package/components/ExternalIntegration/Driver/Lti1p1/ManageProviders.vue +220 -0
- package/components/ExternalIntegration/Driver/ManageLti1p1.vue +45 -0
- package/components/Integration/Driver/Disabled.vue +29 -0
- package/components/SecretField.vue +50 -0
- package/config/integration.config.js +11 -0
- package/helpers/Driver/BlackboardUltra.ts +15 -0
- package/helpers/Driver/Canvas.ts +12 -0
- package/helpers/Driver/Desire2Learn.ts +15 -0
- package/helpers/Driver/GoogleClassroom.ts +15 -0
- package/helpers/Driver/Moodle.ts +12 -0
- package/i18n/en-US/components/external_integration/driver/lti1p1.ts +26 -0
- package/i18n/en-US/components/external_integration/index.ts +5 -0
- package/i18n/en-US/components/index.ts +2 -0
- package/i18n/en-US/components/integration/driver.ts +19 -1
- package/i18n/en-US/pages/course/external_integration/index.ts +6 -0
- package/i18n/en-US/pages/course/index.ts +5 -0
- package/i18n/en-US/pages/index.ts +4 -0
- package/i18n/en-US/pages/login/index.ts +5 -0
- package/i18n/en-US/pages/login/lti.ts +21 -0
- package/i18n/en-US/shared/permission.ts +4 -0
- package/models/ExternalIntegration/Lti1p1Consumer.ts +13 -0
- package/models/ExternalIntegration/Lti1p1Provider.ts +13 -0
- package/package.json +1 -1
- package/pages/admin/vendors.vue +1 -1
- package/pages/course/externalIntegration/index.vue +72 -0
- package/pages/login/lti/error.vue +98 -0
- package/plugin.js +28 -0
- package/test/Components/ExternalIntegration/Lti1p1/ManageConsumer.spec.js +19 -0
- package/test/Components/ExternalIntegration/Lti1p1/ManageConsumers.spec.js +19 -0
- package/test/Components/ExternalIntegration/Lti1p1/ManageProvider.spec.js +19 -0
- package/test/Components/ExternalIntegration/Lti1p1/ManageProviders.spec.js +19 -0
- package/test/Components/ExternalIntegration/ManageLti1p1.spec.js +19 -0
- package/test/Pages/Course/ExternalIntegration/index.spec.js +19 -0
- package/test/Pages/Login/Lti/error.spec.js +19 -0
- package/test/__mocks__/modelMock.js +4 -1
- package/test/mocks.js +1 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
<h1>
|
|
4
|
+
{{
|
|
5
|
+
$t(
|
|
6
|
+
'windward.integrations.components.integration.driver.disabled'
|
|
7
|
+
)
|
|
8
|
+
}}
|
|
9
|
+
</h1>
|
|
10
|
+
</div>
|
|
11
|
+
</template>
|
|
12
|
+
|
|
13
|
+
<script>
|
|
14
|
+
import ManageBaseVue from './ManageBase.vue'
|
|
15
|
+
|
|
16
|
+
export default {
|
|
17
|
+
name: 'ManageAtutorDriver',
|
|
18
|
+
components: {},
|
|
19
|
+
extends: ManageBaseVue,
|
|
20
|
+
data() {
|
|
21
|
+
return {
|
|
22
|
+
// formValid: true|false If this form is "complete" and passed validation on THIS component. Defined and watched in ManageBase.vue
|
|
23
|
+
// render: true|false If we should show the form aka when validation has passed. Defined and managed in ManageBase.vue
|
|
24
|
+
// integration: { metadata: {...} } The integration object to write to. Defined and loaded in ManageBase.vue
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
methods: {},
|
|
28
|
+
}
|
|
29
|
+
</script>
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-text-field :value="value" readonly :type="fieldType">
|
|
3
|
+
<template #append>
|
|
4
|
+
<v-btn icon @click="toggleClear">
|
|
5
|
+
<v-icon>{{ showClear ? 'mdi-eye-off' : 'mdi-eye' }}</v-icon>
|
|
6
|
+
</v-btn>
|
|
7
|
+
<v-btn v-if="copy" icon @click="copyText(value)">
|
|
8
|
+
<v-icon>mdi-content-copy</v-icon>
|
|
9
|
+
</v-btn>
|
|
10
|
+
</template>
|
|
11
|
+
</v-text-field>
|
|
12
|
+
</template>
|
|
13
|
+
|
|
14
|
+
<script>
|
|
15
|
+
export default {
|
|
16
|
+
name: 'SecretField',
|
|
17
|
+
props: {
|
|
18
|
+
value: { type: String, required: false, default: '' },
|
|
19
|
+
hidden: { type: Boolean, required: false, default: true },
|
|
20
|
+
copy: { type: Boolean, required: false, default: true },
|
|
21
|
+
},
|
|
22
|
+
data() {
|
|
23
|
+
return {
|
|
24
|
+
showClear: false,
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
computed: {
|
|
29
|
+
fieldType() {
|
|
30
|
+
if (this.showClear) {
|
|
31
|
+
return 'text'
|
|
32
|
+
} else {
|
|
33
|
+
return 'password'
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
mounted() {
|
|
38
|
+
this.showClear = !this.hidden
|
|
39
|
+
},
|
|
40
|
+
methods: {
|
|
41
|
+
toggleClear() {
|
|
42
|
+
this.showClear = !this.showClear
|
|
43
|
+
},
|
|
44
|
+
copyText(text) {
|
|
45
|
+
navigator.clipboard.writeText(text || '')
|
|
46
|
+
this.$dialog.show(this.$t('shared.forms.copied'))
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
}
|
|
50
|
+
</script>
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import Atutor from '../helpers/Driver/Atutor'
|
|
2
|
+
import BlackboardUltra from '../helpers/Driver/BlackboardUltra'
|
|
3
|
+
import Canvas from '../helpers/Driver/Canvas'
|
|
4
|
+
import Desire2Learn from '../helpers/Driver/Desire2Learn'
|
|
5
|
+
import Moodle from '../helpers/Driver/Moodle'
|
|
6
|
+
import GoogleClassroom from '../helpers/Driver/GoogleClassroom'
|
|
2
7
|
|
|
3
8
|
export default {
|
|
4
9
|
/**
|
|
@@ -9,5 +14,11 @@ export default {
|
|
|
9
14
|
*/
|
|
10
15
|
integrationDrivers: {
|
|
11
16
|
atutor: { driver: Atutor },
|
|
17
|
+
atutor_wgu: { driver: Atutor },
|
|
18
|
+
canvas: { driver: Canvas },
|
|
19
|
+
blackboard_ultra: { driver: BlackboardUltra },
|
|
20
|
+
desire2learn: { driver: Desire2Learn },
|
|
21
|
+
moodle: { driver: Moodle },
|
|
22
|
+
google_classroom: { driver: GoogleClassroom },
|
|
12
23
|
},
|
|
13
24
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// @ts-ignore
|
|
2
|
+
import Manage from '../../components/Integration/Driver/Disabled.vue'
|
|
3
|
+
import DriverInterface, { IntegrationComponents } from './DriverInterface'
|
|
4
|
+
import BaseDriver from './BaseDriver'
|
|
5
|
+
|
|
6
|
+
export default class BlackboardUltra
|
|
7
|
+
extends BaseDriver
|
|
8
|
+
implements DriverInterface
|
|
9
|
+
{
|
|
10
|
+
public components(): IntegrationComponents {
|
|
11
|
+
return {
|
|
12
|
+
Manage,
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// @ts-ignore
|
|
2
|
+
import Manage from '../../components/Integration/Driver/Disabled.vue'
|
|
3
|
+
import DriverInterface, { IntegrationComponents } from './DriverInterface'
|
|
4
|
+
import BaseDriver from './BaseDriver'
|
|
5
|
+
|
|
6
|
+
export default class Canvas extends BaseDriver implements DriverInterface {
|
|
7
|
+
public components(): IntegrationComponents {
|
|
8
|
+
return {
|
|
9
|
+
Manage,
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// @ts-ignore
|
|
2
|
+
import Manage from '../../components/Integration/Driver/Disabled.vue'
|
|
3
|
+
import DriverInterface, { IntegrationComponents } from './DriverInterface'
|
|
4
|
+
import BaseDriver from './BaseDriver'
|
|
5
|
+
|
|
6
|
+
export default class Desire2Learn
|
|
7
|
+
extends BaseDriver
|
|
8
|
+
implements DriverInterface
|
|
9
|
+
{
|
|
10
|
+
public components(): IntegrationComponents {
|
|
11
|
+
return {
|
|
12
|
+
Manage,
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// @ts-ignore
|
|
2
|
+
import Manage from '../../components/Integration/Driver/Disabled.vue'
|
|
3
|
+
import DriverInterface, { IntegrationComponents } from './DriverInterface'
|
|
4
|
+
import BaseDriver from './BaseDriver'
|
|
5
|
+
|
|
6
|
+
export default class GoogleClassroom
|
|
7
|
+
extends BaseDriver
|
|
8
|
+
implements DriverInterface
|
|
9
|
+
{
|
|
10
|
+
public components(): IntegrationComponents {
|
|
11
|
+
return {
|
|
12
|
+
Manage,
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// @ts-ignore
|
|
2
|
+
import Manage from '../../components/Integration/Driver/Disabled.vue'
|
|
3
|
+
import DriverInterface, { IntegrationComponents } from './DriverInterface'
|
|
4
|
+
import BaseDriver from './BaseDriver'
|
|
5
|
+
|
|
6
|
+
export default class Moodle extends BaseDriver implements DriverInterface {
|
|
7
|
+
public components(): IntegrationComponents {
|
|
8
|
+
return {
|
|
9
|
+
Manage,
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
key: 'Key',
|
|
3
|
+
secret: 'Secret',
|
|
4
|
+
auto_key: 'Autogenerated Key',
|
|
5
|
+
auto_secret: 'Autogenerated Secret',
|
|
6
|
+
target_url: 'Target Url',
|
|
7
|
+
launch_url: 'Launch Url',
|
|
8
|
+
new: 'New LTI Link',
|
|
9
|
+
edit: 'Edit LTI Link',
|
|
10
|
+
enabled: 'Enabled',
|
|
11
|
+
provider: 'Provider',
|
|
12
|
+
consumer: 'Consumer',
|
|
13
|
+
provider_panel: 'Provider (Students incoming to Windward)',
|
|
14
|
+
consumer_panel: 'Consumer (Students outgoing from Windward)',
|
|
15
|
+
role_map_panel: 'Role map',
|
|
16
|
+
role_in_host: 'Role in Host LMS',
|
|
17
|
+
role_in_local: 'Role in Windward',
|
|
18
|
+
remote_role: 'Remote Role name',
|
|
19
|
+
map_to_role: 'Map to Windward Role',
|
|
20
|
+
delete_role_map_item: 'Delete role map item',
|
|
21
|
+
add_role_map_item: 'Add role map item',
|
|
22
|
+
role_map_instructions:
|
|
23
|
+
'Only add roles to the below map if the host LMS uses different role names that you want to elevated permissions. Eg "Mentor" that you want to elevate to "External Instructor"',
|
|
24
|
+
role_map_warning:
|
|
25
|
+
'Only add roles to the below map if the host LMS uses different role names that you want to elevated permissions. Eg "Mentor" that you want to elevate to "External Instructor"',
|
|
26
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export default {
|
|
2
2
|
atutor: {
|
|
3
|
-
manage_dialog_title: 'Manage ATutor
|
|
3
|
+
manage_dialog_title: 'Manage ATutor Integration',
|
|
4
4
|
url: 'ATutor API Url',
|
|
5
5
|
url_hint: 'Eg: https://atutor.mindedgecollege.com',
|
|
6
6
|
username: 'Username',
|
|
@@ -8,6 +8,24 @@ export default {
|
|
|
8
8
|
aws_secure_url: 'AWS CDN Url',
|
|
9
9
|
aws_secure_url_hint: 'Eg: https://cdn-d.mindedgecollege.com',
|
|
10
10
|
},
|
|
11
|
+
atutor_wgu: {
|
|
12
|
+
manage_dialog_title: 'Manage ATutor WGU Integration',
|
|
13
|
+
},
|
|
14
|
+
canvas: {
|
|
15
|
+
manage_dialog_title: 'Manage Canvas Integration',
|
|
16
|
+
},
|
|
17
|
+
blackboard_ultra: {
|
|
18
|
+
manage_dialog_title: 'Manage Blackboard Ultra Integration',
|
|
19
|
+
},
|
|
20
|
+
desire2learn: {
|
|
21
|
+
manage_dialog_title: 'Manage Desire2Learn Integration',
|
|
22
|
+
},
|
|
23
|
+
moodle: {
|
|
24
|
+
manage_dialog_title: 'Manage Moodle Integration',
|
|
25
|
+
},
|
|
26
|
+
google_classroom: {
|
|
27
|
+
manage_dialog_title: 'Manage Google Classroom Integration',
|
|
28
|
+
},
|
|
11
29
|
enabled: 'Integration Enabled',
|
|
12
30
|
disabled: 'Integration Disabled',
|
|
13
31
|
ssl_enabled: 'SSL Enabled (Should be enabled for production)',
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import vendor from './vendor'
|
|
2
2
|
import importCourse from './importCourse'
|
|
3
3
|
import importContent from './importContent'
|
|
4
|
+
import login from './login'
|
|
5
|
+
import course from './course'
|
|
4
6
|
|
|
5
7
|
export default {
|
|
6
8
|
vendor,
|
|
7
9
|
import_course: importCourse,
|
|
8
10
|
import_content: importContent,
|
|
11
|
+
login,
|
|
12
|
+
course,
|
|
9
13
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
lti_error: 'LTI Errors',
|
|
3
|
+
launch_error: 'LTI link failed to launch',
|
|
4
|
+
missing_title: 'The below fields are missing:',
|
|
5
|
+
error_title: 'The below errors occurred:',
|
|
6
|
+
error: {
|
|
7
|
+
unknown: 'An unknown error occurred',
|
|
8
|
+
organization: 'Invalid organization',
|
|
9
|
+
tool: 'Invalid tool id',
|
|
10
|
+
tool_organization: 'This tool does not belong to this organization',
|
|
11
|
+
oauth: 'Invalid OAuth. Check your key and secret.',
|
|
12
|
+
},
|
|
13
|
+
missing: {
|
|
14
|
+
context_label:
|
|
15
|
+
'The context label field `context_label` is missing or invalid.',
|
|
16
|
+
resource_link_title:
|
|
17
|
+
'The resource link title `resource_link_title` is missing or invalid.',
|
|
18
|
+
lis_person_contact_email_primary:
|
|
19
|
+
'The users email is missing and an anonymous email could not be generated.',
|
|
20
|
+
},
|
|
21
|
+
}
|
|
@@ -8,6 +8,8 @@ export default {
|
|
|
8
8
|
'Organization Integrations',
|
|
9
9
|
'plugin->windward->integrations->course': 'Course Integrations',
|
|
10
10
|
'plugin->windward->integrations->content': 'Content Integrations',
|
|
11
|
+
'plugin->windward->integrations->course->externalIntegration':
|
|
12
|
+
'External Integrations (LTI / SCORM / etc)',
|
|
11
13
|
},
|
|
12
14
|
|
|
13
15
|
type_description: {
|
|
@@ -22,5 +24,7 @@ export default {
|
|
|
22
24
|
'Access and manage course imports',
|
|
23
25
|
'plugin->windward->integrations->content':
|
|
24
26
|
'Access and manage content imports',
|
|
27
|
+
'plugin->windward->integrations->course->externalIntegration':
|
|
28
|
+
'Access and manage external integrations such as LTI and SCORM',
|
|
25
29
|
},
|
|
26
30
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// @ts-ignore
|
|
2
|
+
import Model from '~/models/Model'
|
|
3
|
+
|
|
4
|
+
export default class Lti1p1Consumer extends Model {
|
|
5
|
+
get required(): string[] {
|
|
6
|
+
return []
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// Set the resource route of the model
|
|
10
|
+
resource() {
|
|
11
|
+
return 'external-integrations/lti/1.1/consumers'
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// @ts-ignore
|
|
2
|
+
import Model from '~/models/Model'
|
|
3
|
+
|
|
4
|
+
export default class Lti1p1Provider extends Model {
|
|
5
|
+
get required(): string[] {
|
|
6
|
+
return []
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// Set the resource route of the model
|
|
10
|
+
resource() {
|
|
11
|
+
return 'external-integrations/lti/1.1/providers'
|
|
12
|
+
}
|
|
13
|
+
}
|
package/package.json
CHANGED
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'
|
|
155
154
|
import Organization from '../../models/Organization'
|
|
156
155
|
import IntegrationJobTable from '../../components/Integration/JobTable.vue'
|
|
156
|
+
import Dialog from '~/components/Dialog.vue'
|
|
157
157
|
|
|
158
158
|
export default {
|
|
159
159
|
name: 'PluginIntegrationsAdminVendorsPage',
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
<h1>
|
|
4
|
+
{{
|
|
5
|
+
$t(
|
|
6
|
+
'windward.integrations.pages.course.external_integration.title'
|
|
7
|
+
)
|
|
8
|
+
}}
|
|
9
|
+
</h1>
|
|
10
|
+
<v-tabs v-model="tab">
|
|
11
|
+
<v-tabs-slider></v-tabs-slider>
|
|
12
|
+
|
|
13
|
+
<v-tab>
|
|
14
|
+
{{
|
|
15
|
+
$t(
|
|
16
|
+
'windward.integrations.pages.course.external_integration.lti_1p1'
|
|
17
|
+
)
|
|
18
|
+
}}
|
|
19
|
+
</v-tab>
|
|
20
|
+
|
|
21
|
+
<v-tab>
|
|
22
|
+
{{
|
|
23
|
+
$t(
|
|
24
|
+
'windward.integrations.pages.course.external_integration.lti_1p3'
|
|
25
|
+
)
|
|
26
|
+
}}
|
|
27
|
+
</v-tab>
|
|
28
|
+
|
|
29
|
+
<v-tab>
|
|
30
|
+
{{
|
|
31
|
+
$t(
|
|
32
|
+
'windward.integrations.pages.course.external_integration.scorm_1p2'
|
|
33
|
+
)
|
|
34
|
+
}}
|
|
35
|
+
</v-tab>
|
|
36
|
+
</v-tabs>
|
|
37
|
+
|
|
38
|
+
<v-tabs-items v-model="tab">
|
|
39
|
+
<v-tab-item> <ManageLti1p1></ManageLti1p1> </v-tab-item>
|
|
40
|
+
<v-tab-item>
|
|
41
|
+
<p class="ma-5">LTI 1.3 Not yet implemented</p>
|
|
42
|
+
</v-tab-item>
|
|
43
|
+
<v-tab-item>
|
|
44
|
+
<p class="ma-5">SCORM 1.2 Not yet implemented</p>
|
|
45
|
+
</v-tab-item>
|
|
46
|
+
</v-tabs-items>
|
|
47
|
+
</div>
|
|
48
|
+
</template>
|
|
49
|
+
|
|
50
|
+
<script>
|
|
51
|
+
import ManageLti1p1 from '../../../components/ExternalIntegration/Driver/ManageLti1p1.vue'
|
|
52
|
+
|
|
53
|
+
export default {
|
|
54
|
+
name: 'PluginIntegrationsExternalIntegrationIndexPage',
|
|
55
|
+
components: { ManageLti1p1 },
|
|
56
|
+
layout: 'authenticated',
|
|
57
|
+
meta: {
|
|
58
|
+
privilege: {
|
|
59
|
+
'plugin.windward.integrations.course.externalIntegration': {
|
|
60
|
+
readable: true,
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
data() {
|
|
65
|
+
return {
|
|
66
|
+
tab: 0,
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
async fetch() {},
|
|
70
|
+
computed: {},
|
|
71
|
+
}
|
|
72
|
+
</script>
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-container>
|
|
3
|
+
<v-divider />
|
|
4
|
+
<v-row>
|
|
5
|
+
<v-col cols="12" md="6" offset-md="3">
|
|
6
|
+
<h1 class="text-center mt-5">
|
|
7
|
+
{{
|
|
8
|
+
$t('windward.integrations.pages.login.lti.launch_error')
|
|
9
|
+
}}
|
|
10
|
+
</h1>
|
|
11
|
+
<v-alert
|
|
12
|
+
v-if="error.length === 0 && missing.length === 0"
|
|
13
|
+
type="error"
|
|
14
|
+
class="mt-5"
|
|
15
|
+
>
|
|
16
|
+
<strong>{{
|
|
17
|
+
$t(
|
|
18
|
+
'windward.integrations.pages.login.lti.error.unknown'
|
|
19
|
+
)
|
|
20
|
+
}}</strong>
|
|
21
|
+
</v-alert>
|
|
22
|
+
<v-alert v-if="missing.length" type="warning" class="mt-5">
|
|
23
|
+
<strong>{{
|
|
24
|
+
$t(
|
|
25
|
+
'windward.integrations.pages.login.lti.missing_title'
|
|
26
|
+
)
|
|
27
|
+
}}</strong>
|
|
28
|
+
<ul>
|
|
29
|
+
<li v-for="missingItem in missing" :key="missingItem">
|
|
30
|
+
{{
|
|
31
|
+
$t(
|
|
32
|
+
'windward.integrations.pages.login.lti.missing.' +
|
|
33
|
+
missingItem
|
|
34
|
+
)
|
|
35
|
+
}}
|
|
36
|
+
</li>
|
|
37
|
+
</ul>
|
|
38
|
+
</v-alert>
|
|
39
|
+
<v-alert v-if="error.length" type="error" class="mt-5">
|
|
40
|
+
<strong>{{
|
|
41
|
+
$t('windward.integrations.pages.login.lti.error_title')
|
|
42
|
+
}}</strong>
|
|
43
|
+
<ul>
|
|
44
|
+
<li v-for="errorItem in error" :key="errorItem">
|
|
45
|
+
{{
|
|
46
|
+
$t(
|
|
47
|
+
'windward.integrations.pages.login.lti.error.' +
|
|
48
|
+
errorItem
|
|
49
|
+
)
|
|
50
|
+
}}
|
|
51
|
+
</li>
|
|
52
|
+
</ul>
|
|
53
|
+
</v-alert>
|
|
54
|
+
</v-col>
|
|
55
|
+
</v-row>
|
|
56
|
+
</v-container>
|
|
57
|
+
</template>
|
|
58
|
+
|
|
59
|
+
<script>
|
|
60
|
+
import _ from 'lodash'
|
|
61
|
+
export default {
|
|
62
|
+
name: 'PluginIntegrationsLoginLtiErrorPage',
|
|
63
|
+
layout: 'default',
|
|
64
|
+
data() {
|
|
65
|
+
return {
|
|
66
|
+
missing: [],
|
|
67
|
+
error: [],
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
async fetch() {},
|
|
71
|
+
computed: {},
|
|
72
|
+
mounted() {
|
|
73
|
+
// Get the missing url parameters to display
|
|
74
|
+
if (!_.isEmpty(_.get(this.$route, 'query.missing', ''))) {
|
|
75
|
+
this.missing = _.get(this.$route, 'query.missing', '')
|
|
76
|
+
.split(',')
|
|
77
|
+
.map((v) => v.trim())
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Get the error url parameters to display
|
|
81
|
+
if (!_.isEmpty(_.get(this.$route, 'query.error', ''))) {
|
|
82
|
+
this.error = _.get(this.$route, 'query.error', '')
|
|
83
|
+
.split(',')
|
|
84
|
+
.map((v) => v.trim())
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Set the appropriate locale
|
|
88
|
+
if (!_.isEmpty(_.get(this.$route, 'query.locale', ''))) {
|
|
89
|
+
const locale = _.get(this.$route, 'query.locale', '')
|
|
90
|
+
|
|
91
|
+
if (this.$i18n.locales.includes(locale)) {
|
|
92
|
+
this.$i18n.setLocale(locale)
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
methods: {},
|
|
97
|
+
}
|
|
98
|
+
</script>
|
package/plugin.js
CHANGED
|
@@ -2,6 +2,8 @@ import enUS from './i18n/en-US'
|
|
|
2
2
|
import AdminVendorsPage from './pages/admin/vendors.vue'
|
|
3
3
|
import AdminImportCoursePage from './pages/admin/importCourse.vue'
|
|
4
4
|
import ImportContentPage from './pages/course/importContent.vue'
|
|
5
|
+
import ExternalIntegrationIndexPage from './pages/course/externalIntegration/index.vue'
|
|
6
|
+
import LoginLtiErrorPage from './pages/login/lti/error.vue'
|
|
5
7
|
import IntegrationHelper from './helpers/IntegrationHelper'
|
|
6
8
|
|
|
7
9
|
export default {
|
|
@@ -41,6 +43,21 @@ export default {
|
|
|
41
43
|
name: 'PluginIntegrationsImportContentPage',
|
|
42
44
|
template: ImportContentPage,
|
|
43
45
|
},
|
|
46
|
+
|
|
47
|
+
{
|
|
48
|
+
page: 'admin-integrations',
|
|
49
|
+
path: '/course/:course/integrations/external',
|
|
50
|
+
i18n: 'windward.integrations.pages.course.external_integration.title',
|
|
51
|
+
name: 'PluginIntegrationsExternalIntegrationIndexPage',
|
|
52
|
+
template: ExternalIntegrationIndexPage,
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
page: 'lti-error',
|
|
56
|
+
path: '/login/lti/error',
|
|
57
|
+
i18n: 'windward.integrations.pages.login.lti.lti_error',
|
|
58
|
+
name: 'PluginIntegrationsLoginLtiErrorPage',
|
|
59
|
+
template: LoginLtiErrorPage,
|
|
60
|
+
},
|
|
44
61
|
],
|
|
45
62
|
components: {
|
|
46
63
|
menu: [
|
|
@@ -78,6 +95,17 @@ export default {
|
|
|
78
95
|
},
|
|
79
96
|
},
|
|
80
97
|
},
|
|
98
|
+
{
|
|
99
|
+
i18n: 'windward.integrations.pages.course.external_integration.title',
|
|
100
|
+
path: '/course/{course.id}/integrations/external',
|
|
101
|
+
context: ['course'],
|
|
102
|
+
permissions: {
|
|
103
|
+
'plugin.windward.integrations.course.externalIntegration':
|
|
104
|
+
{
|
|
105
|
+
readable: true,
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
},
|
|
81
109
|
/*
|
|
82
110
|
{
|
|
83
111
|
i18n: 'windward.integrations.components.navigation.integrations.manage_lti',
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { shallowMount } from '@vue/test-utils'
|
|
2
|
+
|
|
3
|
+
import Vue from 'vue'
|
|
4
|
+
import Vuetify from 'vuetify'
|
|
5
|
+
import { defaultMocks } from '@/test/mocks'
|
|
6
|
+
|
|
7
|
+
import ManageConsumer from '@/components/ExternalIntegration/Driver/Lti1p1/ManageConsumer.vue'
|
|
8
|
+
|
|
9
|
+
Vue.use(Vuetify)
|
|
10
|
+
|
|
11
|
+
describe('ManageConsumer', () => {
|
|
12
|
+
test('ManageConsumer is a Vue instance', () => {
|
|
13
|
+
const wrapper = shallowMount(ManageConsumer, {
|
|
14
|
+
vuetify: new Vuetify(),
|
|
15
|
+
mocks: defaultMocks,
|
|
16
|
+
})
|
|
17
|
+
expect(wrapper.vm).toBeTruthy()
|
|
18
|
+
})
|
|
19
|
+
})
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { shallowMount } from '@vue/test-utils'
|
|
2
|
+
|
|
3
|
+
import Vue from 'vue'
|
|
4
|
+
import Vuetify from 'vuetify'
|
|
5
|
+
import { defaultMocks } from '@/test/mocks'
|
|
6
|
+
|
|
7
|
+
import ManageConsumers from '@/components/ExternalIntegration/Driver/Lti1p1/ManageConsumers.vue'
|
|
8
|
+
|
|
9
|
+
Vue.use(Vuetify)
|
|
10
|
+
|
|
11
|
+
describe('ManageConsumers', () => {
|
|
12
|
+
test('ManageConsumers is a Vue instance', () => {
|
|
13
|
+
const wrapper = shallowMount(ManageConsumers, {
|
|
14
|
+
vuetify: new Vuetify(),
|
|
15
|
+
mocks: defaultMocks,
|
|
16
|
+
})
|
|
17
|
+
expect(wrapper.vm).toBeTruthy()
|
|
18
|
+
})
|
|
19
|
+
})
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { shallowMount } from '@vue/test-utils'
|
|
2
|
+
|
|
3
|
+
import Vue from 'vue'
|
|
4
|
+
import Vuetify from 'vuetify'
|
|
5
|
+
import { defaultMocks } from '@/test/mocks'
|
|
6
|
+
|
|
7
|
+
import ManageProvider from '@/components/ExternalIntegration/Driver/Lti1p1/ManageProvider.vue'
|
|
8
|
+
|
|
9
|
+
Vue.use(Vuetify)
|
|
10
|
+
|
|
11
|
+
describe('ManageProvider', () => {
|
|
12
|
+
test('ManageProvider is a Vue instance', () => {
|
|
13
|
+
const wrapper = shallowMount(ManageProvider, {
|
|
14
|
+
vuetify: new Vuetify(),
|
|
15
|
+
mocks: defaultMocks,
|
|
16
|
+
})
|
|
17
|
+
expect(wrapper.vm).toBeTruthy()
|
|
18
|
+
})
|
|
19
|
+
})
|