@windward/integrations 0.0.7 → 0.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/components/Content/Blocks/ExternalIntegration/LtiConsumer.vue +15 -0
  2. package/components/ExternalIntegration/Driver/Lti1p1/ManageConsumer.vue +3 -7
  3. package/components/ExternalIntegration/Driver/Lti1p1/ManageConsumers.vue +10 -14
  4. package/components/ExternalIntegration/Driver/Lti1p1/ManageProvider.vue +28 -21
  5. package/components/ExternalIntegration/Driver/Lti1p1/ManageProviders.vue +25 -11
  6. package/components/ExternalIntegration/Driver/Lti1p3/ManageProvider.vue +445 -0
  7. package/components/ExternalIntegration/Driver/Lti1p3/ManageProviders.vue +259 -0
  8. package/components/ExternalIntegration/Driver/ManageLti1p1.vue +2 -2
  9. package/components/ExternalIntegration/Driver/ManageLti1p3.vue +45 -0
  10. package/components/ExternalIntegration/ProviderTargetPicker.vue +21 -37
  11. package/components/Integration/Driver/ManageAtutor.vue +15 -0
  12. package/components/Integration/JobLog.vue +98 -0
  13. package/components/Integration/JobTable.vue +15 -1
  14. package/i18n/en-US/components/content/blocks/external_integration/lti_consumer.ts +2 -0
  15. package/i18n/en-US/components/external_integration/driver/lti1p1.ts +0 -21
  16. package/i18n/en-US/components/external_integration/driver/lti1p3.ts +13 -0
  17. package/i18n/en-US/components/external_integration/index.ts +26 -1
  18. package/i18n/en-US/components/integration/driver.ts +1 -0
  19. package/i18n/en-US/components/integration/job.ts +3 -0
  20. package/i18n/en-US/pages/login/lti.ts +1 -1
  21. package/models/ExternalIntegration/{Lti1p1Provider.ts → LtiProvider.ts} +2 -2
  22. package/package.json +1 -1
  23. package/pages/admin/importCourse.vue +1 -1
  24. package/pages/admin/vendors.vue +3 -2
  25. package/pages/course/externalIntegration/index.vue +4 -3
  26. package/plugin.js +48 -1
  27. package/test/Components/ExternalIntegration/Lti1p3/ManageProvider.spec.js +19 -0
  28. package/test/Components/ExternalIntegration/Lti1p3/ManageProviders.spec.js +19 -0
  29. package/test/Components/ExternalIntegration/ManageLti1p3.spec.js +19 -0
  30. package/test/Components/ExternalIntegration/ProviderTargetPicker.spec.js +1 -1
  31. package/test/Components/Integration/JobLog.spec.js +22 -0
  32. package/test/Components/Integration/JobTable.spec.js +23 -0
  33. package/test/__mocks__/componentsMock.js +12 -0
  34. package/test/mocks.js +12 -0
@@ -0,0 +1,259 @@
1
+ <template>
2
+ <div>
3
+ <Dialog
4
+ color="primary"
5
+ action-save
6
+ action-save-new
7
+ @click:save="onSaved"
8
+ >
9
+ <template #title>{{
10
+ $t(
11
+ 'windward.integrations.components.external_integration.driver.lti1p1.new'
12
+ )
13
+ }}</template>
14
+ <template #trigger>{{ $t('shared.forms.new') }}</template>
15
+ <template #form="{ on, attrs }"
16
+ ><ManageProvider v-bind="attrs" v-on="on"></ManageProvider
17
+ ></template>
18
+ </Dialog>
19
+
20
+ <v-data-table
21
+ :headers="headers"
22
+ :items="providers"
23
+ :items-per-page="10"
24
+ class="elevation-1"
25
+ >
26
+ <template #[`item.target`]="{ item }">
27
+ <ProviderTargetViewer
28
+ class="field--target text-truncate"
29
+ :target="item.target"
30
+ ></ProviderTargetViewer>
31
+ </template>
32
+ <template #[`item.metadata.tool_public_keyset_url`]="{ item }">
33
+ <SecretField
34
+ v-model="item.metadata.tool_public_keyset_url"
35
+ :hidden="false"
36
+ ></SecretField>
37
+ </template>
38
+ <template #[`item.metadata.tool_oidc_auth_endpoint`]="{ item }">
39
+ <SecretField
40
+ v-model="item.metadata.tool_oidc_auth_endpoint"
41
+ :hidden="false"
42
+ ></SecretField>
43
+ </template>
44
+ <template #[`item.url`]="{ item }">
45
+ <SecretField v-model="item.url" :hidden="false"></SecretField>
46
+ </template>
47
+
48
+ <template #[`item.enabled`]="{ item }">
49
+ <v-icon :color="item.enabled ? 'success' : 'error'"
50
+ >{{ item.enabled ? 'mdi-check' : 'mdi-close' }}
51
+ </v-icon>
52
+ <span v-if="!item.enabled" class="sr-only">{{
53
+ $t('shared.forms.enabled')
54
+ }}</span>
55
+ </template>
56
+
57
+ <template #[`item.grade_sync`]="{ item }">
58
+ <v-icon :color="item.grade_sync ? 'success' : 'error'"
59
+ >{{ item.grade_sync ? 'mdi-check' : 'mdi-close' }}
60
+ </v-icon>
61
+ <span v-if="!item.grade_sync" class="sr-only">{{
62
+ $t(
63
+ 'windward.integrations.components.external_integration.grade_sync'
64
+ )
65
+ }}</span>
66
+ </template>
67
+
68
+ <template #[`item.created_at`]="{ item }">
69
+ {{ $d(new Date(item.created_at), 'short') }}
70
+ </template>
71
+ <template #[`item.actions`]="{ index, item }">
72
+ <Dialog color="primary" action-save @click:save="onSaved">
73
+ <template #title>{{
74
+ $t(
75
+ 'windward.integrations.components.external_integration.driver.lti1p3.edit'
76
+ )
77
+ }}</template>
78
+ <template #trigger>
79
+ <v-icon small>mdi-pencil</v-icon>
80
+ <span class="sr-only">{{
81
+ $t(
82
+ 'windward.integrations.components.external_integration.driver.lti1p3.edit'
83
+ )
84
+ }}</span>
85
+ </template>
86
+ <template #form="{ on, attrs }"
87
+ ><ManageProvider
88
+ v-model="providers[index]"
89
+ v-bind="attrs"
90
+ v-on="on"
91
+ ></ManageProvider
92
+ ></template>
93
+ </Dialog>
94
+
95
+ <v-btn icon>
96
+ <v-icon @click="onConfirmDelete(item)"> mdi-delete </v-icon>
97
+ <span class="sr-only">{{ $t('shared.forms.delete') }}</span>
98
+ </v-btn>
99
+ </template>
100
+ </v-data-table>
101
+ </div>
102
+ </template>
103
+
104
+ <script>
105
+ import _ from 'lodash'
106
+ import { mapGetters } from 'vuex'
107
+ import LtiProvider from '../../../../models/ExternalIntegration/LtiProvider'
108
+ import SecretField from '../../../SecretField.vue'
109
+ import ProviderTargetViewer from '../../ProviderTargetViewer.vue'
110
+ import ManageProvider from './ManageProvider.vue'
111
+ import Dialog from '~/components/Dialog.vue'
112
+ import Organization from '~/models/Organization'
113
+ import Course from '~/models/Course'
114
+
115
+ export default {
116
+ name: 'ManageLti1p1ProvidersDriver',
117
+ components: { SecretField, Dialog, ManageProvider, ProviderTargetViewer },
118
+ data() {
119
+ return {
120
+ providers: [],
121
+ headers: [
122
+ {
123
+ text: this.$t(
124
+ 'windward.integrations.components.external_integration.target'
125
+ ),
126
+ value: 'target',
127
+ },
128
+ {
129
+ text: this.$t(
130
+ 'windward.integrations.components.external_integration.driver.lti1p3.tool_public_keyset_url'
131
+ ),
132
+ value: 'metadata.tool_public_keyset_url',
133
+ },
134
+ {
135
+ text: this.$t(
136
+ 'windward.integrations.components.external_integration.driver.lti1p3.tool_oidc_auth_endpoint'
137
+ ),
138
+ value: 'metadata.tool_oidc_auth_endpoint',
139
+ },
140
+ {
141
+ text: this.$t(
142
+ 'windward.integrations.components.external_integration.launch_url'
143
+ ),
144
+ value: 'url',
145
+ },
146
+ {
147
+ text: this.$t('shared.forms.enabled'),
148
+ value: 'enabled',
149
+ },
150
+ {
151
+ text: this.$t(
152
+ 'windward.integrations.components.external_integration.grade_sync'
153
+ ),
154
+ value: 'grade_sync',
155
+ },
156
+ { text: this.$t('shared.forms.created'), value: 'created_at' },
157
+ {
158
+ text: this.$t('shared.forms.actions'),
159
+ value: 'actions',
160
+ sortable: false,
161
+ },
162
+ ],
163
+ }
164
+ },
165
+
166
+ async fetch() {
167
+ if (
168
+ !this.$PermissionService.userHasAccessTo(
169
+ 'plugin.windward.integrations.course.externalIntegration',
170
+ 'readable'
171
+ ) ||
172
+ _.isEmpty(this.organization.id) ||
173
+ _.isEmpty(this.course.id)
174
+ ) {
175
+ // Display an angry error that they can't view this driver
176
+ this.$dialog.error(this.$t('shared.error.description_401'), {
177
+ duration: null,
178
+ action: {
179
+ text: this.$t('shared.forms.close'),
180
+ onClick: (_e, toastObject) => {
181
+ toastObject.goAway(0)
182
+ },
183
+ },
184
+ })
185
+ if (_.isEmpty(this.organization.id) || _.isEmpty(this.course.id)) {
186
+ // eslint-disable-next-line no-console
187
+ console.error(
188
+ 'Cannot load external integrations because organization or course is not set!'
189
+ )
190
+ } else {
191
+ // eslint-disable-next-line no-console
192
+ console.error(
193
+ 'You do not have access to this external integration!'
194
+ )
195
+ }
196
+
197
+ // Return so we don't even attempt loading
198
+ return false
199
+ }
200
+
201
+ await this.loadProviders()
202
+ },
203
+ computed: {
204
+ ...mapGetters({
205
+ organization: 'organization/get',
206
+ course: 'course/get',
207
+ }),
208
+ },
209
+ methods: {
210
+ onSaved() {
211
+ this.loadProviders()
212
+ },
213
+ async loadProviders() {
214
+ this.providers = await new LtiProvider()
215
+ .for(
216
+ new Organization({ id: this.organization.id }),
217
+ new Course({ id: this.course.id })
218
+ )
219
+ .where('version', '1.3')
220
+ .get()
221
+ },
222
+ onConfirmDelete(provider) {
223
+ this.$dialog.show(this.$t('shared.forms.confirm_delete_text'), {
224
+ icon: 'mdi-help',
225
+ duration: null,
226
+ action: [
227
+ {
228
+ text: this.$t('shared.forms.cancel'),
229
+ onClick: (_e, toastObject) => {
230
+ toastObject.goAway(0)
231
+ },
232
+ },
233
+ {
234
+ text: this.$t('shared.forms.confirm'),
235
+ // router navigation
236
+ onClick: (_e, toastObject) => {
237
+ this.deleteProvider(provider)
238
+ toastObject.goAway(0)
239
+ },
240
+ },
241
+ ],
242
+ })
243
+ },
244
+ async deleteProvider(provider) {
245
+ await provider.delete()
246
+ this.$dialog.success(this.$t('shared.response.deleted'))
247
+ // Reload providers now that we deleted one
248
+ this.loadProviders()
249
+ },
250
+ },
251
+ }
252
+ </script>
253
+
254
+ <style scoped>
255
+ .field--target {
256
+ max-width: 15em;
257
+ display: inline-block;
258
+ }
259
+ </style>
@@ -5,7 +5,7 @@
5
5
  <v-expansion-panel-header>
6
6
  {{
7
7
  $t(
8
- 'windward.integrations.components.external_integration.driver.lti1p1.provider_panel'
8
+ 'windward.integrations.components.external_integration.provider_panel_title'
9
9
  )
10
10
  }}
11
11
  </v-expansion-panel-header>
@@ -17,7 +17,7 @@
17
17
  <v-expansion-panel-header>
18
18
  {{
19
19
  $t(
20
- 'windward.integrations.components.external_integration.driver.lti1p1.consumer_panel'
20
+ 'windward.integrations.components.external_integration.consumer_panel_title'
21
21
  )
22
22
  }}
23
23
  </v-expansion-panel-header>
@@ -0,0 +1,45 @@
1
+ <template>
2
+ <div>
3
+ <v-expansion-panels v-model="panel">
4
+ <v-expansion-panel>
5
+ <v-expansion-panel-header>
6
+ {{
7
+ $t(
8
+ 'windward.integrations.components.external_integration.provider_panel_title'
9
+ )
10
+ }}
11
+ </v-expansion-panel-header>
12
+ <v-expansion-panel-content>
13
+ <ManageProviders></ManageProviders>
14
+ </v-expansion-panel-content>
15
+ </v-expansion-panel>
16
+ <v-expansion-panel>
17
+ <v-expansion-panel-header>
18
+ {{
19
+ $t(
20
+ 'windward.integrations.components.external_integration.consumer_panel_title'
21
+ )
22
+ }}
23
+ </v-expansion-panel-header>
24
+ <v-expansion-panel-content>
25
+ <!-- <ManageConsumers></ManageConsumers>-->
26
+ </v-expansion-panel-content>
27
+ </v-expansion-panel>
28
+ </v-expansion-panels>
29
+ </div>
30
+ </template>
31
+
32
+ <script>
33
+ import ManageProviders from './Lti1p3/ManageProviders.vue'
34
+ /* import ManageConsumers from './Lti1p3/ManageConsumers.vue' */
35
+
36
+ export default {
37
+ name: 'ManageLti1p3Driver',
38
+ components: { ManageProviders },
39
+ data() {
40
+ return {
41
+ panel: 0,
42
+ }
43
+ },
44
+ }
45
+ </script>
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <div>
3
3
  <v-radio-group
4
- v-model="localMetadata.target_type"
4
+ v-model="provider.target_type"
5
5
  row
6
6
  @change="onTargetTypeChange"
7
7
  >
@@ -50,10 +50,9 @@
50
50
 
51
51
  <div
52
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'
53
+ provider.target_type === 'course_content' ||
54
+ provider.target_type === 'locked_course_content_children' ||
55
+ provider.target_type === 'locked_course_content'
57
56
  "
58
57
  class="content-tree secondary"
59
58
  >
@@ -91,15 +90,13 @@ import { mapGetters } from 'vuex'
91
90
  export default {
92
91
  name: 'ExternalIntegrationProviderTargetPicker',
93
92
  props: {
94
- target: { type: String, required: true, default: '' },
95
- metadata: { type: Object, required: true, default: () => {} },
93
+ value: { type: Object, required: true },
96
94
  },
97
95
  data() {
98
96
  return {
99
97
  selectedContent: null,
100
98
  selectedTreeviewContent: [],
101
- localTarget: '',
102
- localMetadata: {},
99
+ provider: {},
103
100
  }
104
101
  },
105
102
  computed: {
@@ -110,41 +107,28 @@ export default {
110
107
  },
111
108
  watch: {
112
109
  // Apply any changes coming up
113
- target: {
110
+ value: {
114
111
  handler(value) {
115
- this.localTarget = _.cloneDeep(value)
116
- },
117
- },
118
- metadata: {
119
- deep: true,
120
- handler(value) {
121
- this.localMetadata = _.cloneDeep(value)
112
+ this.provider = _.cloneDeep(value)
122
113
  },
123
114
  },
124
115
  },
125
116
  mounted() {
126
117
  // Init our local vars
127
- this.localTarget = _.cloneDeep(this.target)
128
- this.localMetadata = _.cloneDeep(this.metadata)
118
+ this.provider = _.cloneDeep(this.value)
129
119
 
130
120
  // Set the target_type key if it doesn't exist
131
- if (!this.localMetadata.target_type) {
132
- this.localMetadata.target_type = ''
121
+ if (!this.provider.target_type) {
122
+ this.provider.target_type = 'course'
133
123
  }
134
124
 
135
125
  // 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
- )
126
+ if (this.provider.target) {
127
+ if (!_.isEmpty(this.provider.course_content_id)) {
128
+ this.setSelectedContentById(this.provider.course_content_id)
145
129
  }
146
130
  }
147
- this.sync(this.localMetadata.target_type)
131
+ this.sync(this.provider.target_type)
148
132
  },
149
133
  methods: {
150
134
  setSelectedContentById(id) {
@@ -161,13 +145,14 @@ export default {
161
145
  targetType === 'locked_course_content_children')
162
146
  ) {
163
147
  url = `/course/${this.course.id}/content/${this.selectedContent.id}`
148
+ this.provider.course_content_id = this.selectedContent.id
164
149
  } else if (targetType === 'course') {
165
150
  url = `/course/${this.course.id}/`
151
+ this.provider.course_content_id = null
166
152
  }
167
- this.localTarget = url
153
+ this.provider.target = url
168
154
  // Sync up the changes to the parent component
169
- this.$emit('update:target', this.localTarget)
170
- this.$emit('update:metadata', this.localMetadata)
155
+ this.$emit('input', this.provider)
171
156
  },
172
157
  onTargetTypeChange(e) {
173
158
  // Reset the selected content if you pick by course
@@ -182,8 +167,7 @@ export default {
182
167
  let isIncluded = false
183
168
  // If we aren't including children then return hard false
184
169
  if (
185
- this.localMetadata.target_type !==
186
- 'locked_course_content_children'
170
+ this.provider.target_type !== 'locked_course_content_children'
187
171
  ) {
188
172
  return false
189
173
  }
@@ -220,7 +204,7 @@ export default {
220
204
  this.selectedContent = null
221
205
  }
222
206
 
223
- this.sync(this.localMetadata.target_type)
207
+ this.sync(this.provider.target_type)
224
208
  },
225
209
  },
226
210
  }
@@ -16,6 +16,7 @@
16
16
  />
17
17
 
18
18
  <v-text-field
19
+ ref="atutor_url"
19
20
  v-model="integration.metadata.config.url"
20
21
  :label="
21
22
  $t(
@@ -27,6 +28,7 @@
27
28
  'windward.integrations.components.integration.driver.atutor.url_hint'
28
29
  )
29
30
  "
31
+ :rules="urlValidation"
30
32
  ></v-text-field>
31
33
  <v-text-field
32
34
  v-model="integration.metadata.config.username"
@@ -47,6 +49,7 @@
47
49
  ></v-text-field>
48
50
 
49
51
  <v-text-field
52
+ ref="aws-url"
50
53
  v-model="integration.metadata.config.aws_secure_url"
51
54
  :label="
52
55
  $t(
@@ -58,6 +61,7 @@
58
61
  'windward.integrations.components.integration.driver.atutor.aws_secure_url_hint'
59
62
  )
60
63
  "
64
+ :rules="urlValidation"
61
65
  ></v-text-field>
62
66
 
63
67
  <v-switch
@@ -100,6 +104,17 @@ export default {
100
104
  // integration: { metadata: {...} } The integration object to write to. Defined and loaded in ManageBase.vue
101
105
  errorMessage: '',
102
106
  testConnectionLoading: false,
107
+ urlValidation: [
108
+ (value) => {
109
+ if (value && value.slice(-1) === '/') {
110
+ return this.$t(
111
+ 'windward.integrations.components.integration.driver.remove_slash'
112
+ )
113
+ } else {
114
+ return true
115
+ }
116
+ },
117
+ ],
103
118
  }
104
119
  },
105
120
  methods: {
@@ -0,0 +1,98 @@
1
+ <template>
2
+ <div>
3
+ <v-btn color="primary" outlined @click="onViewLog()">
4
+ <v-icon>mdi-note-search</v-icon>
5
+ </v-btn>
6
+ <Dialog v-model="logDialog" :trigger="false">
7
+ <template #title>{{
8
+ $t('windward.integrations.components.integration.job.view_log')
9
+ }}</template>
10
+ <template #form>
11
+ <v-progress-circular v-if="loading" size="128" indeterminate />
12
+ <div v-if="!loading">
13
+ <SearchField v-model="search" hide-filters></SearchField>
14
+
15
+ <v-alert
16
+ v-for="logItem in filteredLog"
17
+ :key="logItem.id"
18
+ :type="logItem.level"
19
+ >
20
+ {{ logItem.message }}
21
+ </v-alert>
22
+
23
+ <p v-if="filteredLog.length === 0">
24
+ {{
25
+ $t(
26
+ 'windward.integrations.components.integration.job.log_no_results'
27
+ )
28
+ }}
29
+ </p>
30
+ </div>
31
+ </template>
32
+ </Dialog>
33
+ </div>
34
+ </template>
35
+
36
+ <script>
37
+ import { mapGetters } from 'vuex'
38
+ import SearchField from '~/components/SearchField.vue'
39
+ import Organization from '../../models/Organization'
40
+
41
+ export default {
42
+ components: { SearchField },
43
+ name: 'IntegrationJobLog',
44
+ props: {
45
+ id: { type: String, required: true },
46
+ },
47
+ data() {
48
+ return {
49
+ search: {},
50
+ loading: true,
51
+ log: [],
52
+ logDialog: false,
53
+ }
54
+ },
55
+ computed: {
56
+ ...mapGetters({
57
+ organization: 'organization/get',
58
+ }),
59
+ filteredLog() {
60
+ if (!this.search.term || this.search.term.length < 3) {
61
+ return this.log
62
+ }
63
+ const filtered = this.log.filter((item) => {
64
+ return item.message
65
+ .toLowerCase()
66
+ .includes(this.search.term.toLowerCase())
67
+ })
68
+
69
+ return filtered
70
+ },
71
+ },
72
+ methods: {
73
+ async onViewLog() {
74
+ this.logDialog = true
75
+ this.log = []
76
+
77
+ const job = await new Organization({
78
+ id: this.organization.id,
79
+ })
80
+ .integrationJobs()
81
+ .with('log')
82
+ .find(this.id)
83
+
84
+ this.log = job.log
85
+ this.loading = false
86
+ },
87
+ },
88
+ }
89
+ </script>
90
+
91
+ <style scoped>
92
+ .col-progress {
93
+ min-width: 200px;
94
+ }
95
+ .col-details {
96
+ max-width: 100px;
97
+ }
98
+ </style>
@@ -42,7 +42,14 @@
42
42
  <th class="text-left">
43
43
  {{
44
44
  $t(
45
- 'windward.integrations.components.integration.job.created'
45
+ 'windward.integrations.components.integration.job.started'
46
+ )
47
+ }}
48
+ </th>
49
+ <th class="text-left">
50
+ {{
51
+ $t(
52
+ 'windward.integrations.components.integration.job.view_log'
46
53
  )
47
54
  }}
48
55
  </th>
@@ -119,6 +126,9 @@
119
126
  {{ jobDetails(item) }}
120
127
  </td>
121
128
  <td>{{ $d(new Date(item.created_at), 'long') }}</td>
129
+ <td>
130
+ <JobLog :id="item.id"></JobLog>
131
+ </td>
122
132
  </tr>
123
133
  </tbody>
124
134
  </template>
@@ -132,9 +142,11 @@ import _ from 'lodash'
132
142
  import { mapGetters } from 'vuex'
133
143
  import Vendor from '../../models/Vendor'
134
144
  import Organization from '../../models/Organization'
145
+ import JobLog from './JobLog.vue'
135
146
 
136
147
  export default {
137
148
  name: 'IntegrationJobs',
149
+ components: { JobLog },
138
150
  props: {
139
151
  channel: { type: String, required: true },
140
152
  event: { type: String, required: true },
@@ -145,6 +157,8 @@ export default {
145
157
  vendors: [],
146
158
  orgIntegrations: [],
147
159
  jobs: [],
160
+ log: [],
161
+ logDialog: false,
148
162
  }
149
163
  },
150
164
  async fetch() {
@@ -2,6 +2,8 @@ export default {
2
2
  launch: 'Launch',
3
3
  configure_warning:
4
4
  'This block needs to be configured. Please select a LTI tool in the settings panel.',
5
+ no_access:
6
+ 'You do not have permissions to launch this link. Please contact your system administrator.',
5
7
  missing_tool: 'The tool id {0} is missing',
6
8
  unknown_error: 'Something went wrong! Could not launch this link!',
7
9
  link_disabled: 'Link disabled',
@@ -1,6 +1,4 @@
1
1
  export default {
2
- name: 'Name',
3
- description: 'Description',
4
2
  key: 'Key',
5
3
  secret: 'Secret',
6
4
  parameter_name: 'Custom Parameter Name',
@@ -11,25 +9,6 @@ export default {
11
9
  change_secret: 'Change Secret',
12
10
  new_key: 'New Key',
13
11
  new_secret: 'New Secret',
14
- target: 'Target',
15
- target_url: 'Target Url',
16
- launch_url: 'Launch Url',
17
12
  new: 'New LTI Link',
18
13
  edit: 'Edit LTI Link',
19
- enabled: 'Enabled',
20
- provider: 'Provider',
21
- consumer: 'Consumer',
22
- provider_panel: 'Provider (Students incoming to Windward)',
23
- consumer_panel: 'Consumer (Students outgoing from Windward)',
24
- role_map_panel: 'Role map',
25
- role_in_host: 'Role in Host LMS',
26
- role_in_local: 'Role in Windward',
27
- remote_role: 'Remote Role name',
28
- map_to_role: 'Map to Windward Role',
29
- delete_role_map_item: 'Delete role map item',
30
- add_role_map_item: 'Add role map item',
31
- role_map_instructions:
32
- '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"',
33
- role_map_warning:
34
- '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"',
35
14
  }