@windward/core 0.15.0 → 0.17.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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ### Release [0.17.0] created - 2025-05-13
4
+
5
+
6
+ ### Release [0.16.0] created - 2025-04-29
7
+
8
+
3
9
  ### Release [0.15.0] created - 2025-04-09
4
10
 
5
11
 
@@ -1,11 +1,11 @@
1
1
  <template>
2
2
  <div>
3
3
  <v-container
4
- class="pa-0"
5
4
  v-if="
6
5
  block.metadata.config.title ||
7
6
  block.metadata.config.instructions
8
7
  "
8
+ class="pa-0"
9
9
  >
10
10
  <h2 v-if="block.metadata.config.title" tabindex="0">
11
11
  {{ block.metadata.config.title }}
@@ -31,9 +31,10 @@
31
31
  :key="itemIndex"
32
32
  >
33
33
  <v-expansion-panel-header
34
+ :ref="'expansion-panel-' + itemIndex"
34
35
  class="expansion-panel-header"
35
36
  color="primary"
36
- :ref="'expansion-panel-' + itemIndex"
37
+ role="button"
37
38
  @click="onOpenAccordion(itemIndex)"
38
39
  >
39
40
  {{
@@ -43,8 +44,8 @@
43
44
  }}
44
45
  </v-expansion-panel-header>
45
46
  <v-expansion-panel-content
46
- class="expansion-panel-body"
47
47
  :key="expansionPanelKey"
48
+ class="expansion-panel-body"
48
49
  >
49
50
  <v-container
50
51
  class="px-0 d-flex"
@@ -87,9 +88,9 @@
87
88
  import _ from 'lodash'
88
89
  import Crypto from '~/helpers/Crypto'
89
90
  import ImageAssetViewer from '~/components/Content/ImageAssetViewer.vue'
91
+ import BaseContentBlock from '~/components/Content/Blocks/BaseContentBlock'
90
92
  import TextEditor from '~/components/Text/TextEditor'
91
93
  import TextViewer from '~/components/Text/TextViewer'
92
- import BaseContentBlock from '~/components/Content/Blocks/BaseContentBlock'
93
94
 
94
95
  export default {
95
96
  name: 'ContentBlockAccordion',
@@ -99,40 +100,6 @@ export default {
99
100
  ImageAssetViewer,
100
101
  },
101
102
  extends: BaseContentBlock,
102
- beforeMount() {
103
- if (_.isEmpty(this.block)) {
104
- this.block = {}
105
- }
106
- if (_.isEmpty(this.block.metadata)) {
107
- this.block.metadata = {}
108
- }
109
- if (_.isEmpty(this.block.metadata.config)) {
110
- this.block.metadata.config = {}
111
- }
112
- if (_.isEmpty(this.block.metadata.config.title)) {
113
- this.block.metadata.config.title = ''
114
- }
115
- if (_.isEmpty(this.block.metadata.config.items)) {
116
- const defaultObject = {
117
- header: '',
118
- expand: false,
119
- content: '',
120
- fileConfig: {
121
- display: {
122
- width: 100,
123
- margin: '',
124
- padding: '',
125
- },
126
- hideBackground: true,
127
- },
128
- }
129
- this.block.metadata.config.items = []
130
- this.block.metadata.config.items.push(defaultObject)
131
- }
132
- this.block.body = this.$t(
133
- 'windward.core.shared.content_blocks.title.accordion'
134
- )
135
- },
136
103
  data() {
137
104
  return {
138
105
  expansionPanelKey: '0',
@@ -184,6 +151,40 @@ export default {
184
151
  }
185
152
  },
186
153
  },
154
+ beforeMount() {
155
+ if (_.isEmpty(this.block)) {
156
+ this.block = {}
157
+ }
158
+ if (_.isEmpty(this.block.metadata)) {
159
+ this.block.metadata = {}
160
+ }
161
+ if (_.isEmpty(this.block.metadata.config)) {
162
+ this.block.metadata.config = {}
163
+ }
164
+ if (_.isEmpty(this.block.metadata.config.title)) {
165
+ this.block.metadata.config.title = ''
166
+ }
167
+ if (_.isEmpty(this.block.metadata.config.items)) {
168
+ const defaultObject = {
169
+ header: '',
170
+ expand: false,
171
+ content: '',
172
+ fileConfig: {
173
+ display: {
174
+ width: 100,
175
+ margin: '',
176
+ padding: '',
177
+ },
178
+ hideBackground: true,
179
+ },
180
+ }
181
+ this.block.metadata.config.items = []
182
+ this.block.metadata.config.items.push(defaultObject)
183
+ }
184
+ this.block.body = this.$t(
185
+ 'windward.core.shared.content_blocks.title.accordion'
186
+ )
187
+ },
187
188
  mounted() {
188
189
  if (this.render) {
189
190
  // ensure panels are always loaded closed
@@ -34,7 +34,9 @@
34
34
  <v-row>
35
35
  <v-col cols="12">
36
36
  <p>
37
- {{ citation }}
37
+ <span>{{
38
+ citation && source ? citation + ',' : citation
39
+ }}</span>
38
40
  <span :class="sourceClass">{{ source }}</span>
39
41
  </p>
40
42
  </v-col>
@@ -51,38 +53,10 @@ import BaseContentBlock from '~/components/Content/Blocks/BaseContentBlock'
51
53
 
52
54
  export default {
53
55
  name: 'ContentBlockTab',
54
- extends: BaseContentBlock,
55
- beforeMount() {
56
- if (_.isEmpty(this.block)) {
57
- this.block = {}
58
- }
59
- if (_.isEmpty(this.block.metadata)) {
60
- this.block.metadata = {}
61
- }
62
- if (_.isEmpty(this.block.metadata.config)) {
63
- this.block.metadata.config = {}
64
- }
65
- if (_.isEmpty(this.block.metadata.config.title)) {
66
- this.block.metadata.config.title = ''
67
- }
68
- if (_.isEmpty(this.block.metadata.config.instructions)) {
69
- this.block.metadata.config.instructions = ''
70
- }
71
- if (_.isEmpty(this.block.metadata.config.block_quote)) {
72
- this.block.metadata.config.block_quote = {
73
- quote: '',
74
- author: '',
75
- author_title: '',
76
- organization: '',
77
- source_title: '',
78
- source_type: '',
79
- source_url: '',
80
- }
81
- }
82
- this.block.body = this.$t(
83
- 'windward.core.components.content.blocks.block_quote.body'
84
- )
56
+ components: {
57
+ TextViewer,
85
58
  },
59
+ extends: BaseContentBlock,
86
60
  data() {
87
61
  return {}
88
62
  },
@@ -101,7 +75,6 @@ export default {
101
75
  parts.push(value)
102
76
  }
103
77
  }
104
-
105
78
  // If there were parts to return then prepend with a mdash
106
79
  if (parts.length > 0) {
107
80
  return he.decode('&mdash;') + parts.join(', ')
@@ -113,24 +86,23 @@ export default {
113
86
  const parts = []
114
87
 
115
88
  const sourceTitle =
116
- this.block.metadata.config.block_quote['source_title'] || ''
89
+ this.block.metadata.config.block_quote.source_title || ''
117
90
  const sourceType =
118
- this.block.metadata.config.block_quote['source_type'] || ''
91
+ this.block.metadata.config.block_quote.source_type || ''
119
92
 
120
- if (sourceTitle && sourceType) {
93
+ if (sourceType) {
121
94
  switch (sourceType) {
122
95
  case 'online_journal':
123
96
  // Wrap the sourceTitle for online journals in quotes
124
- parts.push('"' + sourceTitle + '"')
97
+ if (!_.isEmpty(sourceTitle)) {
98
+ parts.push('"' + sourceTitle + '"')
99
+ }
125
100
 
126
101
  // For online journals also add the url if it exists
127
- if (
128
- this.block.metadata.config.block_quote['source_url']
129
- ) {
102
+ if (this.block.metadata.config.block_quote.source_url) {
130
103
  parts.push(
131
- this.block.metadata.config.block_quote[
132
- 'source_url'
133
- ]
104
+ this.block.metadata.config.block_quote
105
+ .source_url
134
106
  )
135
107
  }
136
108
  break
@@ -140,7 +112,6 @@ export default {
140
112
  break
141
113
  }
142
114
  }
143
-
144
115
  // If the citation is empty (aka we only have sources)
145
116
  // and there's sources then prepend with a mdash
146
117
  if (parts.length > 0 && this.citation === '') {
@@ -154,14 +125,47 @@ export default {
154
125
  },
155
126
  sourceClass() {
156
127
  if (
157
- this.block.metadata.config.block_quote['source_title'] &&
158
- this.block.metadata.config.block_quote['source_type'] &&
159
- this.block.metadata.config.block_quote['source_type'] === 'book'
128
+ this.block.metadata.config.block_quote.source_title &&
129
+ this.block.metadata.config.block_quote.source_type &&
130
+ this.block.metadata.config.block_quote.source_type === 'book'
160
131
  ) {
161
132
  return 'span-title'
133
+ } else {
134
+ return ''
162
135
  }
163
136
  },
164
137
  },
138
+ beforeMount() {
139
+ if (_.isEmpty(this.block)) {
140
+ this.block = {}
141
+ }
142
+ if (_.isEmpty(this.block.metadata)) {
143
+ this.block.metadata = {}
144
+ }
145
+ if (_.isEmpty(this.block.metadata.config)) {
146
+ this.block.metadata.config = {}
147
+ }
148
+ if (_.isEmpty(this.block.metadata.config.title)) {
149
+ this.block.metadata.config.title = ''
150
+ }
151
+ if (_.isEmpty(this.block.metadata.config.instructions)) {
152
+ this.block.metadata.config.instructions = ''
153
+ }
154
+ if (_.isEmpty(this.block.metadata.config.block_quote)) {
155
+ this.block.metadata.config.block_quote = {
156
+ quote: '',
157
+ author: '',
158
+ author_title: '',
159
+ organization: '',
160
+ source_title: '',
161
+ source_type: '',
162
+ source_url: '',
163
+ }
164
+ }
165
+ this.block.body = this.$t(
166
+ 'windward.core.components.content.blocks.block_quote.body'
167
+ )
168
+ },
165
169
  mounted() {},
166
170
  methods: {},
167
171
  }
@@ -1,11 +1,11 @@
1
1
  <template>
2
2
  <div>
3
3
  <v-container
4
- class="pa-0"
5
4
  v-if="
6
5
  block.metadata.config.title ||
7
6
  block.metadata.config.instructions
8
7
  "
8
+ class="pa-0"
9
9
  >
10
10
  <h2 v-if="block.metadata.config.title" tabindex="0">
11
11
  {{ block.metadata.config.title }}
@@ -23,6 +23,7 @@
23
23
  <div v-if="block.body && !submitted">
24
24
  <TextViewer v-model="block.body" :height="200"></TextViewer>
25
25
  <TextEditor
26
+ :key="updateKey"
26
27
  v-model="response"
27
28
  :height="200"
28
29
  menubar=""
@@ -104,23 +105,25 @@
104
105
  <script>
105
106
  import _ from 'lodash'
106
107
  import { mapGetters } from 'vuex'
107
- import TextViewer from '~/components/Text/TextViewer'
108
- import TextEditor from '~/components/Text/TextEditor'
109
108
  import BaseContentBlock from '~/components/Content/Blocks/BaseContentBlock'
110
109
  import UserContentBlockState from '~/models/UserContentBlockState'
110
+ import Crypto from '~/helpers/Crypto'
111
+ import TextViewer from '~/components/Text/TextViewer'
112
+ import TextEditor from '~/components/Text/TextEditor'
111
113
 
112
114
  export default {
113
115
  name: 'ContentBlockOpenResponse',
114
- extends: BaseContentBlock,
115
116
  components: {
116
117
  TextViewer,
117
118
  TextEditor,
118
119
  },
120
+ extends: BaseContentBlock,
119
121
  data() {
120
122
  return {
121
123
  stateLoaded: false,
122
124
  response: '',
123
125
  submitted: false,
126
+ updateKey: Crypto.id(),
124
127
  }
125
128
  },
126
129
  computed: {
@@ -135,6 +138,13 @@ export default {
135
138
  )
136
139
  },
137
140
  },
141
+ watch: {
142
+ render(newVal) {
143
+ if (newVal) {
144
+ this.onAfterSetContentBlockState()
145
+ }
146
+ },
147
+ },
138
148
  beforeMount() {
139
149
  if (_.isEmpty(this.block.body)) {
140
150
  this.block.body = ''
@@ -155,7 +165,6 @@ export default {
155
165
  this.block.metadata.config.starting_text = ''
156
166
  }
157
167
  },
158
- watch: {},
159
168
  mounted() {},
160
169
  methods: {
161
170
  async onAfterSetContentBlockState() {
@@ -181,11 +190,14 @@ export default {
181
190
  }
182
191
 
183
192
  // If after the state is applied the response is still empty then apply the default response
184
- if (this.response === '') {
193
+ if (_.isEmpty(this.response)) {
185
194
  this.response = this.block.metadata.config.starting_text
186
195
  }
196
+ } else {
197
+ // If we don't have a block_id then we are in the initial setup state
198
+ this.response = this.block.metadata.config.starting_text
187
199
  }
188
-
200
+ this.updateKey = Crypto.id()
189
201
  this.stateLoaded = true
190
202
  },
191
203
  onSubmit() {
@@ -1,24 +1,36 @@
1
1
  <template>
2
- <v-list-item
3
- :to="
4
- '/course/' +
5
- course.id +
6
- '/section/' +
7
- enrollment.course_section_id +
8
- '/user-uploads'
9
- "
10
- >
11
- <v-list-item-action>
12
- <v-icon>mdi-cloud-upload</v-icon>
13
- </v-list-item-action>
14
- <v-list-item-content>
15
- <v-list-item-title
16
- >{{
17
- $t('windward.core.components.navigation.user_upload.title')
18
- }}
19
- </v-list-item-title>
20
- </v-list-item-content>
21
- </v-list-item>
2
+ <v-tooltip right>
3
+ <template #activator="{ on, attrs }">
4
+ <v-list-item
5
+ :class="color"
6
+ :to="
7
+ '/course/' +
8
+ course.id +
9
+ '/section/' +
10
+ enrollment.course_section_id +
11
+ '/user-uploads'
12
+ "
13
+ v-bind="attrs"
14
+ v-on="on"
15
+ >
16
+ <v-list-item-action>
17
+ <v-icon>mdi-cloud-upload</v-icon>
18
+ </v-list-item-action>
19
+ <v-list-item-content>
20
+ <v-list-item-title
21
+ >{{
22
+ $t(
23
+ 'windward.core.components.navigation.user_upload.title'
24
+ )
25
+ }}
26
+ </v-list-item-title>
27
+ </v-list-item-content>
28
+ </v-list-item>
29
+ </template>
30
+ <span>{{
31
+ $t('windward.core.components.navigation.user_upload.title')
32
+ }}</span>
33
+ </v-tooltip>
22
34
  </template>
23
35
 
24
36
  <script>
@@ -27,6 +39,9 @@ import { mapGetters } from 'vuex'
27
39
  export default {
28
40
  components: {},
29
41
  middleware: ['auth'],
42
+ props: {
43
+ color: { type: String, required: false, default: '' },
44
+ },
30
45
  data() {
31
46
  return {}
32
47
  },
@@ -5,6 +5,7 @@
5
5
  autofill
6
6
  :disabled="render"
7
7
  allow-read
8
+ root-block="p"
8
9
  show-glossary
9
10
  :hide-text-editor="hideTextEditor"
10
11
  >
@@ -67,6 +67,9 @@ export default {
67
67
  </script>
68
68
 
69
69
  <style lang="scss">
70
+ .text-viewer {
71
+ overflow-x: auto !important;
72
+ }
70
73
  .text-viewer table tr td {
71
74
  padding: 10px !important;
72
75
  }
@@ -30,7 +30,8 @@
30
30
  color="primary"
31
31
  elevation="0"
32
32
  outlined
33
- @click="show = false"
33
+ @click="close"
34
+ @keydown.esc="close"
34
35
  >
35
36
  {{
36
37
  $t(
@@ -46,12 +47,11 @@
46
47
 
47
48
  <div class="fib">
48
49
  <v-text-field
50
+ v-model="userInput"
49
51
  :disabled="false"
50
52
  outlined
51
53
  dense
52
- v-model="userInput"
53
54
  clear-icon="mdi-close-circle-outline"
54
- @click:append-outer="toggleToolTip"
55
55
  clearable
56
56
  :background-color="feedback"
57
57
  :placeholder="
@@ -59,18 +59,19 @@
59
59
  'windward.core.components.utils.fill_in_the_blank.fill_in_blank_input.add_answer'
60
60
  )
61
61
  "
62
- @input="showAnswer = false"
63
- @keydown="onPressEnter"
64
62
  :aria-label="
65
63
  $t(
66
64
  'windward.core.components.utils.tiny_mce_wrapper.fill_in_blank'
67
65
  )
68
66
  "
67
+ @click:append-outer="toggleToolTip"
68
+ @input="showAnswer = false"
69
+ @keydown="onPressEnter"
69
70
  ></v-text-field>
70
71
  &nbsp;
71
72
  <v-btn
72
73
  v-if="userInput && userInput.length > 0"
73
- @click="toggleToolTip"
74
+ ref="btnCheck"
74
75
  elevation="0"
75
76
  color="primary"
76
77
  outlined
@@ -79,25 +80,22 @@
79
80
  'windward.core.components.utils.fill_in_the_blank.fill_in_blank_input.check_answer'
80
81
  )
81
82
  "
83
+ @click="toggleToolTip"
82
84
  >{{
83
- show
84
- ? $t(
85
- 'windward.core.components.utils.fill_in_the_blank.fill_in_blank_input.reset'
86
- )
87
- : $t(
88
- 'windward.core.components.utils.fill_in_the_blank.fill_in_blank_input.check'
89
- )
85
+ $t(
86
+ 'windward.core.components.utils.fill_in_the_blank.fill_in_blank_input.check'
87
+ )
90
88
  }}</v-btn
91
89
  >
92
90
  </div>
93
91
  </span>
94
92
  </template>
95
93
  <script>
96
- import ContentViewer from '../ContentViewer.vue'
97
94
  import _ from 'lodash'
95
+
98
96
  export default {
99
97
  name: 'FillInBlankInput',
100
- components: { ContentViewer },
98
+ components: {},
101
99
  props: {
102
100
  answer: { type: String, required: true },
103
101
  description: {
@@ -144,6 +142,20 @@ export default {
144
142
  return ''
145
143
  },
146
144
  },
145
+ watch: {
146
+ // set focus on the action button when dialog loaded for accessibility
147
+ show: function (newValue) {
148
+ if (newValue) {
149
+ this.timerId = setTimeout(() => {
150
+ this.setFocusAction()
151
+ }, 100)
152
+ } else {
153
+ if (this.timerId !== '') {
154
+ clearTimeout(this.timeout)
155
+ }
156
+ }
157
+ },
158
+ },
147
159
  methods: {
148
160
  setFocusAction() {
149
161
  this.$refs.action_button_1.$el.focus()
@@ -171,19 +183,11 @@ export default {
171
183
 
172
184
  this.show = !this.show
173
185
  },
174
- },
175
- watch: {
176
- //set focus on the action button when dialog loaded for accessibility
177
- show: function (newValue) {
178
- if (newValue) {
179
- this.timerId = setTimeout(() => {
180
- this.setFocusAction()
181
- }, 100)
182
- } else {
183
- if (this.timerId !== '') {
184
- clearTimeout(this.timeout)
185
- }
186
- }
186
+ close() {
187
+ this.show = false
188
+ this.$nextTick(() => {
189
+ this.$refs.btnCheck.$el.focus()
190
+ })
187
191
  },
188
192
  },
189
193
  }