@explorer-1/vue 0.2.51 → 0.2.52
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.d.ts +2 -0
- package/dist/explorer-1-vue.js +3228 -3167
- package/dist/explorer-1-vue.umd.cjs +10 -10
- package/dist/img/SwimlaneCTA/backgroundImages/JPL_is__Artists.jpg +0 -0
- package/dist/img/SwimlaneCTA/backgroundImages/JPL_is__Communicators.jpg +0 -0
- package/dist/img/SwimlaneCTA/backgroundImages/JPL_is__Designers.jpg +0 -0
- package/dist/img/SwimlaneCTA/backgroundImages/JPL_is__Disruptors.jpg +0 -0
- package/dist/img/SwimlaneCTA/backgroundImages/JPL_is__Dreamers.jpg +0 -0
- package/dist/img/SwimlaneCTA/backgroundImages/JPL_is__Educators.jpg +0 -0
- package/dist/img/SwimlaneCTA/backgroundImages/JPL_is__Innovators.jpg +0 -0
- package/dist/img/SwimlaneCTA/backgroundImages/JPL_is__Inventors.jpg +0 -0
- package/dist/img/SwimlaneCTA/backgroundImages/JPL_is__Makers.jpg +0 -0
- package/dist/img/SwimlaneCTA/backgroundImages/JPL_is__Problem_Solvers.jpg +0 -0
- package/dist/img/SwimlaneCTA/backgroundImages/JPL_is__Robiticists.jpg +0 -0
- package/dist/img/SwimlaneCTA/backgroundImages/JPL_is__Scientists.jpg +0 -0
- package/dist/img/SwimlaneCTA/backgroundImages/JPL_is__Software_Engineers.jpg +0 -0
- package/dist/img/SwimlaneCTA/backgroundImages/JPL_is__Thinkers.jpg +0 -0
- package/dist/img/SwimlaneCTA/backgroundImages/JPL_is__Visualizers.jpg +0 -0
- package/dist/img/SwimlaneCTA/backgroundImagesSmall/JPL_is__Artists.jpg +0 -0
- package/dist/img/SwimlaneCTA/backgroundImagesSmall/JPL_is__Communicators.jpg +0 -0
- package/dist/img/SwimlaneCTA/backgroundImagesSmall/JPL_is__Designers.jpg +0 -0
- package/dist/img/SwimlaneCTA/backgroundImagesSmall/JPL_is__Disruptors.jpg +0 -0
- package/dist/img/SwimlaneCTA/backgroundImagesSmall/JPL_is__Dreamers.jpg +0 -0
- package/dist/img/SwimlaneCTA/backgroundImagesSmall/JPL_is__Educators.jpg +0 -0
- package/dist/img/SwimlaneCTA/backgroundImagesSmall/JPL_is__Innovators.jpg +0 -0
- package/dist/img/SwimlaneCTA/backgroundImagesSmall/JPL_is__Inventors.jpg +0 -0
- package/dist/img/SwimlaneCTA/backgroundImagesSmall/JPL_is__Makers.jpg +0 -0
- package/dist/img/SwimlaneCTA/backgroundImagesSmall/JPL_is__Problem_Solvers.jpg +0 -0
- package/dist/img/SwimlaneCTA/backgroundImagesSmall/JPL_is__Robiticists.jpg +0 -0
- package/dist/img/SwimlaneCTA/backgroundImagesSmall/JPL_is__Scientists.jpg +0 -0
- package/dist/img/SwimlaneCTA/backgroundImagesSmall/JPL_is__Software_Engineers.jpg +0 -0
- package/dist/img/SwimlaneCTA/backgroundImagesSmall/JPL_is__Thinkers.jpg +0 -0
- package/dist/img/SwimlaneCTA/backgroundImagesSmall/JPL_is__Visualizers.jpg +0 -0
- package/dist/src/components/BaseButton/BaseButton.stories.d.ts +1 -1
- package/dist/src/components/BaseButton/BaseButton.vue.d.ts +1 -1
- package/dist/src/components/BaseModal/BaseModal.stories.d.ts +2 -2
- package/dist/src/components/BlockStreamfield/BlockStreamfield.vue.d.ts +12 -0
- package/dist/src/components/HomepageMissionsCarousel/HomepageMissionsCarousel.stories.d.ts +5 -1
- package/dist/src/components/HomepageMissionsCarousel/HomepageMissionsCarouselItem.vue.d.ts +5 -1
- package/dist/src/components/SearchFilterGroup/SearchFilterGroup.vue.d.ts +1 -0
- package/dist/src/components/SearchResultCard/SearchResultCard.vue.d.ts +9 -0
- package/dist/src/components/SearchResultGridItem/SearchResultGridItem.vue.d.ts +9 -0
- package/dist/src/components/TextInput/TextInput.vue.d.ts +5 -2
- package/dist/src/components/YearTicker/YearTicker.stories.d.ts +1 -0
- package/dist/src/components/YearTicker/YearTicker.vue.d.ts +1 -0
- package/dist/src/interfaces.d.ts +4 -2
- package/dist/src/templates/edu/PageEduLesson/PageEduLesson.stories.d.ts +3 -5
- package/dist/src/templates/edu/PageEduStudentProject/PageEduStudentProject.stories.d.ts +601 -0
- package/dist/src/utils/generateHash.d.ts +1 -0
- package/dist/style.css +1 -1
- package/package.json +2 -2
- package/src/components/BlockIframeEmbed/BlockIframeEmbed.vue +1 -1
- package/src/components/BlockImage/BlockImage.vue +4 -1
- package/src/components/BlockImage/BlockImageFullBleed.vue +5 -2
- package/src/components/BlockImage/BlockImageStandard.vue +5 -2
- package/src/components/BlockImageCarouselItem/BlockImageCarouselItem.vue +5 -2
- package/src/components/BlockImageComparison/BlockImageComparison.vue +5 -2
- package/src/components/BlockInlineImage/BlockInlineImage.vue +9 -2
- package/src/components/BlockStreamfield/BlockStreamfield.vue +46 -23
- package/src/components/BlockVideo/BlockVideo.vue +1 -1
- package/src/components/BlockVideoEmbed/BlockVideoEmbed.vue +1 -1
- package/src/components/HeroInlineMedia/HeroInlineMedia.vue +2 -21
- package/src/components/HeroMedia/HeroMedia.vue +1 -1
- package/src/components/MetaPanel/MetaPanel.vue +48 -43
- package/src/components/SearchResultsList/SearchResultsList.vue +4 -1
- package/src/templates/edu/PageEduLesson/PageEduLesson.stories.js +1 -1
- package/src/templates/edu/PageEduLesson/PageEduLesson.vue +9 -7
- package/src/templates/edu/PageEduLesson/PageEduLessonSection.vue +3 -8
- package/src/templates/edu/PageEduStudentProject/PageEduStudentProject.stories.js +253 -0
- package/src/templates/edu/PageEduStudentProject/PageEduStudentProject.vue +419 -0
- package/src/templates/edu/PageEduStudentProject/PageEduStudentProjectSection.vue +179 -0
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import {
|
|
3
|
-
import { camelCase } from 'lodash'
|
|
2
|
+
import { reactive } from 'vue'
|
|
4
3
|
import type { ImageObject, StreamfieldBlockData } from './../../../interfaces'
|
|
5
4
|
import BlockHeading, {
|
|
6
5
|
type BlockHeadingObject
|
|
@@ -28,19 +27,15 @@ const props = withDefaults(defineProps<PageEduLessonSectionProps>(), {
|
|
|
28
27
|
image: undefined
|
|
29
28
|
})
|
|
30
29
|
|
|
31
|
-
const { heading, blocks, image } = reactive(props)
|
|
32
|
-
|
|
33
|
-
const anchorId = computed(() => {
|
|
34
|
-
return 'lesson_' + camelCase(heading?.heading)
|
|
35
|
-
})
|
|
30
|
+
const { heading, blocks, image, procedures, text } = reactive(props)
|
|
36
31
|
</script>
|
|
37
32
|
<template>
|
|
38
33
|
<section
|
|
39
|
-
:id="anchorId"
|
|
40
34
|
class="PageEduLessonSection"
|
|
41
35
|
:aria-label="heading?.heading"
|
|
42
36
|
>
|
|
43
37
|
<LayoutHelper
|
|
38
|
+
v-if="heading"
|
|
44
39
|
indent="col-3"
|
|
45
40
|
class="lg:mb-8 mb-5"
|
|
46
41
|
>
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
import { HeroMediaData } from './../../../components/HeroMedia/HeroMedia.stories'
|
|
2
|
+
import { BlockIframeEmbedData } from './../../../components/BlockIframeEmbed/BlockIframeEmbed.stories.js'
|
|
3
|
+
import { BlockImageCarouselData } from './../../../components/BlockImageCarousel/BlockImageCarousel.stories'
|
|
4
|
+
import { BlockImageData } from './../../../components/BlockImage/BlockImage.stories'
|
|
5
|
+
import { BlockInlineImageData } from './../../../components/BlockInlineImage/BlockInlineImage.stories'
|
|
6
|
+
import { BlockHeadingData } from './../../../components/BlockHeading/BlockHeading.stories'
|
|
7
|
+
import { BlockImageComparisonData } from './../../../components/BlockImageComparison/BlockImageComparison.stories'
|
|
8
|
+
import { BaseVideoData } from './../../../components/BaseVideo/BaseVideo.stories'
|
|
9
|
+
import { BlockVideoEmbedData } from './../../../components/BlockVideoEmbed/BlockVideoEmbed.stories'
|
|
10
|
+
import { BlockRelatedLinksData } from './../../../components/BlockRelatedLinks/BlockRelatedLinks.stories.js'
|
|
11
|
+
import { BlockLinkCardCarouselData } from './../../../components/BlockLinkCarousel/BlockLinkCarousel.stories.js'
|
|
12
|
+
import {
|
|
13
|
+
BlockStreamfieldTruncatedData,
|
|
14
|
+
BlockStreamfieldMinimalData
|
|
15
|
+
} from './../../../components/BlockStreamfield/BlockStreamfield.stories'
|
|
16
|
+
import PageEduStudentProject from './PageEduStudentProject.vue'
|
|
17
|
+
import { AboutTheAuthorData } from './../../../components/AboutTheAuthor/AboutTheAuthor.stories'
|
|
18
|
+
|
|
19
|
+
export default {
|
|
20
|
+
title: 'Templates/EDU/PageEduStudentProject',
|
|
21
|
+
component: PageEduStudentProject,
|
|
22
|
+
tags: ['!autodocs'],
|
|
23
|
+
decorators: [
|
|
24
|
+
() => ({
|
|
25
|
+
template: `<div id="storyDecorator" class="disable-nav-offset"><story/></div>`
|
|
26
|
+
})
|
|
27
|
+
],
|
|
28
|
+
parameters: {
|
|
29
|
+
layout: 'fullscreen',
|
|
30
|
+
html: {
|
|
31
|
+
root: '#storyDecorator'
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
excludeStories: /.*Data$/
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const BaseStory = {
|
|
38
|
+
args: {
|
|
39
|
+
data: {
|
|
40
|
+
__typename: 'EDUStudentProjectPage',
|
|
41
|
+
title: 'Test Student Project',
|
|
42
|
+
url: '/edu/resources/test-student-project',
|
|
43
|
+
pageType: 'EDUStudentProjectPage',
|
|
44
|
+
contentType: 'edu_resources.EDUStudentProjectPage',
|
|
45
|
+
searchDescription: '',
|
|
46
|
+
seoTitle: 'Test Student Project',
|
|
47
|
+
slug: 'test-student-project',
|
|
48
|
+
publicationDate: '2024-08-16',
|
|
49
|
+
lastPublishedAt: '2024-08-22T02:33:13.507206+00:00',
|
|
50
|
+
thumbnailImage: {
|
|
51
|
+
__typename: 'CustomImage',
|
|
52
|
+
original: 'http://127.0.0.1:9000/media/original_images/imagessirtfsirtf-090303-16.jpg',
|
|
53
|
+
alt: ''
|
|
54
|
+
},
|
|
55
|
+
authors: AboutTheAuthorData,
|
|
56
|
+
hero: [
|
|
57
|
+
{
|
|
58
|
+
...HeroMediaData,
|
|
59
|
+
blockType: 'HeroImageBlock'
|
|
60
|
+
}
|
|
61
|
+
],
|
|
62
|
+
|
|
63
|
+
lesson: {
|
|
64
|
+
title: 'Lesson',
|
|
65
|
+
url: '/path-to-student-project'
|
|
66
|
+
},
|
|
67
|
+
|
|
68
|
+
primarySubject: {
|
|
69
|
+
subject: 'Arts'
|
|
70
|
+
},
|
|
71
|
+
additionalSubjects: [
|
|
72
|
+
{
|
|
73
|
+
subject: 'Science'
|
|
74
|
+
}
|
|
75
|
+
],
|
|
76
|
+
gradeLevels: [
|
|
77
|
+
{
|
|
78
|
+
gradeLevel: 'K'
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
gradeLevel: '1'
|
|
82
|
+
}
|
|
83
|
+
],
|
|
84
|
+
time: {
|
|
85
|
+
time: 'Under 30 mins'
|
|
86
|
+
},
|
|
87
|
+
customTime: undefined,
|
|
88
|
+
standards: [
|
|
89
|
+
{
|
|
90
|
+
standard: {
|
|
91
|
+
code: 'CCRA.R.1',
|
|
92
|
+
definition:
|
|
93
|
+
'Read closely to determine what the text says explicitly and to make logical inferences from it; cite specific textual evidence when writing or speaking to support conclusions drawn from the text.',
|
|
94
|
+
domain: {
|
|
95
|
+
domain: 'College and Career Readiness Anchor Standards for Reading'
|
|
96
|
+
},
|
|
97
|
+
type: 'ccss_english_language_arts'
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
standard: {
|
|
102
|
+
code: 'RL.1.5',
|
|
103
|
+
definition:
|
|
104
|
+
'Explain major differences between books that tell stories and books that give information, drawing on a wide reading of a range of text types.',
|
|
105
|
+
domain: {
|
|
106
|
+
domain: 'Reading Standards for Literature'
|
|
107
|
+
},
|
|
108
|
+
type: 'ccss_english_language_arts'
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
standard: {
|
|
113
|
+
code: 'K-PS2-1',
|
|
114
|
+
definition:
|
|
115
|
+
'Plan and conduct an investigation to compare the effects of different strengths or different directions of pushes and pulls on the motion of an object.',
|
|
116
|
+
domain: {
|
|
117
|
+
domain: 'Physical Sciences'
|
|
118
|
+
},
|
|
119
|
+
type: 'ngss'
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
],
|
|
123
|
+
|
|
124
|
+
overview: BlockStreamfieldMinimalData.body,
|
|
125
|
+
overviewHeading: undefined,
|
|
126
|
+
overviewImage: BlockImageData.image,
|
|
127
|
+
|
|
128
|
+
materials:
|
|
129
|
+
'<ul><li data-block-key="nvq4l">list item one</li><li data-block-key="efmt7">list item two</li><li data-block-key="d0f66">list item three this one is really long and the text just keeps on going lorem ipsum dolor sit amet consectatur</li></ul><p data-block-key="bksrq">Paragraph to appear below.</p>',
|
|
130
|
+
materialsHeading: 'Custom Materials Heading',
|
|
131
|
+
materialsImage: BlockImageData.image,
|
|
132
|
+
|
|
133
|
+
stepsNumbering: false,
|
|
134
|
+
|
|
135
|
+
steps: [
|
|
136
|
+
{
|
|
137
|
+
heading: 'Lorem ipsum dolor no media',
|
|
138
|
+
media: [],
|
|
139
|
+
content: [BlockImageData, ...BlockStreamfieldMinimalData.body, BlockInlineImageData.block]
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
heading: 'Sit amet',
|
|
143
|
+
media: [
|
|
144
|
+
{
|
|
145
|
+
blockType: 'VideoBlock',
|
|
146
|
+
video: BaseVideoData,
|
|
147
|
+
caption: 'Lorem ipsum dolor sit amet',
|
|
148
|
+
credit: 'NASA/JPL'
|
|
149
|
+
}
|
|
150
|
+
],
|
|
151
|
+
content: BlockStreamfieldMinimalData.body
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
heading: 'Consectatur adipscing',
|
|
155
|
+
media: [BlockImageComparisonData],
|
|
156
|
+
content: BlockStreamfieldMinimalData.body
|
|
157
|
+
}
|
|
158
|
+
],
|
|
159
|
+
|
|
160
|
+
customSections: [
|
|
161
|
+
{
|
|
162
|
+
blockType: 'EDUStudentProjectCustomSectionBlock',
|
|
163
|
+
content: BlockStreamfieldTruncatedData.body,
|
|
164
|
+
heading: BlockHeadingData,
|
|
165
|
+
position: 'after_overview'
|
|
166
|
+
}
|
|
167
|
+
],
|
|
168
|
+
|
|
169
|
+
body: BlockStreamfieldTruncatedData.body,
|
|
170
|
+
|
|
171
|
+
relatedLinks: BlockRelatedLinksData.data,
|
|
172
|
+
relatedContentHeading: 'Related Content',
|
|
173
|
+
relatedContent: BlockLinkCardCarouselData
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export const HeroCarousel = {
|
|
179
|
+
args: {
|
|
180
|
+
data: {
|
|
181
|
+
...BaseStory.args.data,
|
|
182
|
+
hero: [{ blockType: 'CarouselBlock', blocks: BlockImageCarouselData }]
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export const HeroImageComparison = {
|
|
188
|
+
args: {
|
|
189
|
+
data: {
|
|
190
|
+
...BaseStory.args.data,
|
|
191
|
+
hero: [
|
|
192
|
+
{
|
|
193
|
+
...BlockImageComparisonData
|
|
194
|
+
}
|
|
195
|
+
]
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
export const HeroVideo = {
|
|
201
|
+
args: {
|
|
202
|
+
data: {
|
|
203
|
+
...BaseStory.args.data,
|
|
204
|
+
hero: [
|
|
205
|
+
{
|
|
206
|
+
blockType: 'VideoBlock',
|
|
207
|
+
video: BaseVideoData,
|
|
208
|
+
caption: 'Lorem ipsum dolor sit amet',
|
|
209
|
+
credit: 'NASA/JPL'
|
|
210
|
+
}
|
|
211
|
+
]
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export const HeroVideoEmbed = {
|
|
217
|
+
args: {
|
|
218
|
+
data: {
|
|
219
|
+
...BaseStory.args.data,
|
|
220
|
+
hero: [
|
|
221
|
+
{
|
|
222
|
+
...BlockVideoEmbedData.data,
|
|
223
|
+
embed: {
|
|
224
|
+
embed: `<iframe title="Meet NASA's Diana Trujillo - Embedded Hero" width="480" height="270" src="https://www.youtube.com/embed/vUuUyYqI83Q?feature=oembed" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>`
|
|
225
|
+
},
|
|
226
|
+
blockType: 'VideoEmbedBlock'
|
|
227
|
+
}
|
|
228
|
+
]
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export const HeroIframeEmbed = {
|
|
234
|
+
args: {
|
|
235
|
+
data: {
|
|
236
|
+
...BaseStory.args.data,
|
|
237
|
+
hero: [
|
|
238
|
+
{
|
|
239
|
+
...BlockIframeEmbedData
|
|
240
|
+
}
|
|
241
|
+
]
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
export const NoHero = {
|
|
247
|
+
args: {
|
|
248
|
+
data: {
|
|
249
|
+
...BaseStory.args.data,
|
|
250
|
+
hero: []
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed, reactive, ref } from 'vue'
|
|
3
|
+
import type {
|
|
4
|
+
ImageObject,
|
|
5
|
+
PageEduResourcesObject,
|
|
6
|
+
StreamfieldBlockData
|
|
7
|
+
} from './../../../interfaces'
|
|
8
|
+
import HeroMedia from './../../../components/HeroMedia/HeroMedia.vue'
|
|
9
|
+
import BaseLink from './../../../components/BaseLink/BaseLink.vue'
|
|
10
|
+
import type { BlockHeadingObject } from '../../../components/BlockHeading/BlockHeading.vue'
|
|
11
|
+
import BlockLinkCarousel from './../../../components/BlockLinkCarousel/BlockLinkCarousel.vue'
|
|
12
|
+
import LayoutHelper from './../../../components/LayoutHelper/LayoutHelper.vue'
|
|
13
|
+
import DetailHeadline from './../../../components/DetailHeadline/DetailHeadline.vue'
|
|
14
|
+
import ShareButtonsEdu from './../../../components/ShareButtonsEdu/ShareButtonsEdu.vue'
|
|
15
|
+
import BlockStreamfield from './../../../components/BlockStreamfield/BlockStreamfield.vue'
|
|
16
|
+
import BlockRelatedLinks from '../../../components/BlockRelatedLinks/BlockRelatedLinks.vue'
|
|
17
|
+
import MetaPanel from '../../../components/MetaPanel/MetaPanel.vue'
|
|
18
|
+
import MetaPanelItems from '../../../components/MetaPanelItems/MetaPanelItems.vue'
|
|
19
|
+
import PageEduStudentProjectSection, {
|
|
20
|
+
type PageEduStudentProjectSectionProps
|
|
21
|
+
} from './PageEduStudentProjectSection.vue'
|
|
22
|
+
import NavJumpMenu from './../../../components/NavJumpMenu/NavJumpMenu.vue'
|
|
23
|
+
import HeroInlineMedia from './../../../components/HeroInlineMedia/HeroInlineMedia.vue'
|
|
24
|
+
import AboutTheAuthor from './../../../components/AboutTheAuthor/AboutTheAuthor.vue'
|
|
25
|
+
|
|
26
|
+
import { HeadingLevel } from '../../../components/BaseHeading/BaseHeading.vue'
|
|
27
|
+
import StudentProjectBadge from '@explorer-1/common/src/images/svg/student-project-badge.svg'
|
|
28
|
+
|
|
29
|
+
interface EduStudentProjectSectionObject extends PageEduStudentProjectSectionProps {
|
|
30
|
+
type?: string
|
|
31
|
+
}
|
|
32
|
+
export interface EduStudentProjectStep {
|
|
33
|
+
heading?: string
|
|
34
|
+
media?: StreamfieldBlockData[]
|
|
35
|
+
content?: StreamfieldBlockData[]
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
interface PageEduStudentProjectObject extends PageEduResourcesObject {
|
|
39
|
+
[key: string]: any
|
|
40
|
+
studentProject: {
|
|
41
|
+
title: string
|
|
42
|
+
urlPath: string
|
|
43
|
+
}
|
|
44
|
+
overview: StreamfieldBlockData[]
|
|
45
|
+
overviewHeading: string
|
|
46
|
+
overviewImage: ImageObject
|
|
47
|
+
materials: string
|
|
48
|
+
materialsHeading: string
|
|
49
|
+
materialsImage: ImageObject
|
|
50
|
+
steps: EduStudentProjectStep[]
|
|
51
|
+
stepsHeading: string
|
|
52
|
+
stepsStepsNumbering?: boolean
|
|
53
|
+
customSections: any
|
|
54
|
+
}
|
|
55
|
+
interface PageEduStudentProjectProps {
|
|
56
|
+
data?: PageEduStudentProjectObject
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const props = withDefaults(defineProps<PageEduStudentProjectProps>(), {
|
|
60
|
+
data: undefined
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
const { data } = reactive(props)
|
|
64
|
+
|
|
65
|
+
const PageEduStudentProjectJumpMenu = ref()
|
|
66
|
+
|
|
67
|
+
defineExpose({
|
|
68
|
+
PageEduStudentProjectJumpMenu
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
const stringAsHeadingBlockData = (
|
|
72
|
+
heading: HeadingLevel,
|
|
73
|
+
overrideText?: string
|
|
74
|
+
): BlockHeadingObject => {
|
|
75
|
+
return {
|
|
76
|
+
blockType: 'HeadingBlock',
|
|
77
|
+
heading: (overrideText || heading) as HeadingLevel,
|
|
78
|
+
level: 'h2'
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const heroEmpty = computed((): boolean => {
|
|
83
|
+
return data?.hero?.length === 0
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
const heroInline = computed((): boolean => {
|
|
87
|
+
// heroes with interactive elements have special handling
|
|
88
|
+
if (!heroEmpty.value && data?.hero) {
|
|
89
|
+
// excludes VideoBlock as this will autoplay
|
|
90
|
+
if (data?.hero[0].blockType === 'VideoBlock') {
|
|
91
|
+
return false
|
|
92
|
+
} else if (
|
|
93
|
+
data?.hero[0].blockType === 'CarouselBlock' ||
|
|
94
|
+
data?.hero[0].blockType === 'IframeEmbedBlock' ||
|
|
95
|
+
data?.hero[0].blockType === 'VideoEmbedBlock' ||
|
|
96
|
+
data?.hero[0].blockType === 'ImageComparisonBlock'
|
|
97
|
+
) {
|
|
98
|
+
return true
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return false
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
const sectionOrder = ['top', 'overview', 'materials', 'steps', 'bottom']
|
|
105
|
+
|
|
106
|
+
// mimic HeadingBlock data shape for defined section headings
|
|
107
|
+
const staticSectionHeadings = computed((): { [key: string]: BlockHeadingObject } | undefined => {
|
|
108
|
+
if (data) {
|
|
109
|
+
const result = sectionOrder.reduce<Record<string, BlockHeadingObject>>((acc, section) => {
|
|
110
|
+
// only include the heading if the section has content
|
|
111
|
+
if (data[section]?.length) {
|
|
112
|
+
const headingText =
|
|
113
|
+
section === 'steps' ? 'Project Steps' : section.charAt(0).toUpperCase() + section.slice(1)
|
|
114
|
+
acc[section] = stringAsHeadingBlockData(
|
|
115
|
+
(data[`${section}Heading`] as HeadingLevel) || headingText
|
|
116
|
+
)
|
|
117
|
+
}
|
|
118
|
+
return acc
|
|
119
|
+
}, {})
|
|
120
|
+
return result
|
|
121
|
+
}
|
|
122
|
+
return undefined
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
const keyedCustomSections = computed(
|
|
126
|
+
():
|
|
127
|
+
| {
|
|
128
|
+
[key: string]: StreamfieldBlockData[]
|
|
129
|
+
}
|
|
130
|
+
| undefined => {
|
|
131
|
+
if (data) {
|
|
132
|
+
const result = data.customSections.reduce(
|
|
133
|
+
(
|
|
134
|
+
acc: { [key: string]: StreamfieldBlockData[] },
|
|
135
|
+
section: {
|
|
136
|
+
heading: StreamfieldBlockData
|
|
137
|
+
content: StreamfieldBlockData[]
|
|
138
|
+
position: string
|
|
139
|
+
}
|
|
140
|
+
) => {
|
|
141
|
+
const position = section.position
|
|
142
|
+
if (!acc[position]) {
|
|
143
|
+
acc[position] = []
|
|
144
|
+
}
|
|
145
|
+
acc[position].push(section.heading)
|
|
146
|
+
acc[position].push(...section.content)
|
|
147
|
+
return acc
|
|
148
|
+
},
|
|
149
|
+
{}
|
|
150
|
+
)
|
|
151
|
+
return result
|
|
152
|
+
}
|
|
153
|
+
return undefined
|
|
154
|
+
}
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
const consolidatedBlocks = computed(() => {
|
|
158
|
+
// NavJumpMenu handles filtering for HeadingBlock, so we don't need to do that here
|
|
159
|
+
const blocks = []
|
|
160
|
+
// include custom top blocks
|
|
161
|
+
if (keyedCustomSections.value && keyedCustomSections.value['top']) {
|
|
162
|
+
blocks.push(...keyedCustomSections.value['top'])
|
|
163
|
+
}
|
|
164
|
+
// include predefined section blocks
|
|
165
|
+
sectionOrder.forEach((section) => {
|
|
166
|
+
if (data && data[section]) {
|
|
167
|
+
if (staticSectionHeadings.value && staticSectionHeadings.value[section]) {
|
|
168
|
+
blocks.push(staticSectionHeadings.value[section])
|
|
169
|
+
}
|
|
170
|
+
if (section !== 'materials' && section !== 'steps') {
|
|
171
|
+
blocks.push(...data[section])
|
|
172
|
+
} else if (section === 'steps' && data.steps?.length) {
|
|
173
|
+
// get blocks in nested steps
|
|
174
|
+
data.steps.forEach((item) => {
|
|
175
|
+
if (item.content?.length) {
|
|
176
|
+
blocks.push(...item.content)
|
|
177
|
+
}
|
|
178
|
+
})
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
// include custom "after_" blocks
|
|
182
|
+
if (keyedCustomSections.value && keyedCustomSections.value[`after_${section}`]) {
|
|
183
|
+
blocks.push(...keyedCustomSections.value[`after_${section}`])
|
|
184
|
+
}
|
|
185
|
+
})
|
|
186
|
+
// include custom bottom blocks
|
|
187
|
+
if (keyedCustomSections.value && keyedCustomSections.value['bottom']) {
|
|
188
|
+
blocks.push(...keyedCustomSections.value['bottom'])
|
|
189
|
+
}
|
|
190
|
+
// include body blocks
|
|
191
|
+
if (data?.body?.length) {
|
|
192
|
+
blocks.push(...data.body)
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return blocks
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
// organize data to render with PageEduStudentProjectSection component
|
|
199
|
+
const consolidatedSections = computed((): EduStudentProjectSectionObject[] => {
|
|
200
|
+
const sections: EduStudentProjectSectionObject[] = []
|
|
201
|
+
// include custom top section
|
|
202
|
+
if (keyedCustomSections.value && keyedCustomSections.value['top']) {
|
|
203
|
+
sections.push({ type: 'streamfield', blocks: keyedCustomSections.value['top'] })
|
|
204
|
+
}
|
|
205
|
+
sectionOrder.forEach((section) => {
|
|
206
|
+
if (data && data[section]) {
|
|
207
|
+
sections.push({
|
|
208
|
+
heading: staticSectionHeadings.value ? staticSectionHeadings.value[section] : undefined,
|
|
209
|
+
blocks: section !== 'materials' && section !== 'steps' ? data[section] : undefined,
|
|
210
|
+
text: section === 'materials' ? data[section] : undefined,
|
|
211
|
+
steps: section === 'steps' ? data[section] : undefined
|
|
212
|
+
})
|
|
213
|
+
}
|
|
214
|
+
// include custom "after_" sections
|
|
215
|
+
if (keyedCustomSections.value && keyedCustomSections.value[`after_${section}`]) {
|
|
216
|
+
sections.push({ type: 'streamfield', blocks: keyedCustomSections.value[`after_${section}`] })
|
|
217
|
+
}
|
|
218
|
+
})
|
|
219
|
+
// include custom bottom section
|
|
220
|
+
if (keyedCustomSections.value && keyedCustomSections.value['bottom']) {
|
|
221
|
+
sections.push({ type: 'streamfield', blocks: keyedCustomSections.value['bottom'] })
|
|
222
|
+
}
|
|
223
|
+
const filteredSections = sections.filter(
|
|
224
|
+
(item) => item.text || item.blocks?.length || item.steps?.length
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
return filteredSections
|
|
228
|
+
})
|
|
229
|
+
|
|
230
|
+
const studentBadge = computed(() => {
|
|
231
|
+
return StudentProjectBadge
|
|
232
|
+
})
|
|
233
|
+
</script>
|
|
234
|
+
<template>
|
|
235
|
+
<div
|
|
236
|
+
v-if="data"
|
|
237
|
+
class="ThemeVariantLight pt-5 lg:pt-12"
|
|
238
|
+
>
|
|
239
|
+
<div class="BaseGrid hidden lg:block container relative mx-auto z-20 pointer-events-none">
|
|
240
|
+
<div class="absolute top-0 left-0 col-start-1 col-end-3 text-right lg:-ml-2 xl:ml-4">
|
|
241
|
+
<img
|
|
242
|
+
:src="studentBadge"
|
|
243
|
+
alt=""
|
|
244
|
+
width="200"
|
|
245
|
+
height="200"
|
|
246
|
+
class="block w-full h-auto"
|
|
247
|
+
/>
|
|
248
|
+
</div>
|
|
249
|
+
</div>
|
|
250
|
+
<LayoutHelper
|
|
251
|
+
indent="col-3"
|
|
252
|
+
class="mb-10"
|
|
253
|
+
>
|
|
254
|
+
<DetailHeadline
|
|
255
|
+
v-if="data.title"
|
|
256
|
+
:title="data.title"
|
|
257
|
+
label="Student Project"
|
|
258
|
+
pill
|
|
259
|
+
pill-color="secondary"
|
|
260
|
+
/>
|
|
261
|
+
<ShareButtonsEdu
|
|
262
|
+
v-if="data?.url"
|
|
263
|
+
class="mt-4"
|
|
264
|
+
:url="data.url"
|
|
265
|
+
:title="data.title"
|
|
266
|
+
:image="data.thumbnailImage?.original"
|
|
267
|
+
/>
|
|
268
|
+
<div
|
|
269
|
+
v-if="data?.lesson?.url"
|
|
270
|
+
class="mt-8 font-bold text-body-lg"
|
|
271
|
+
>
|
|
272
|
+
Want to teach this?
|
|
273
|
+
<BaseLink
|
|
274
|
+
class="font-normal inline text-action underline hover:text-action-dark cursor-pointer"
|
|
275
|
+
variant="none"
|
|
276
|
+
:to="data.lesson.url"
|
|
277
|
+
>
|
|
278
|
+
View the Lesson Plan
|
|
279
|
+
</BaseLink>
|
|
280
|
+
</div>
|
|
281
|
+
</LayoutHelper>
|
|
282
|
+
|
|
283
|
+
<div class="container relative mx-auto z-20 pointer-events-none">
|
|
284
|
+
<img
|
|
285
|
+
:src="studentBadge"
|
|
286
|
+
alt=""
|
|
287
|
+
width="150"
|
|
288
|
+
height="150"
|
|
289
|
+
class="absolute -mt-16 sm:-mt-24 right-0 lg:hidden md:w-[185px] md:h-[185px]"
|
|
290
|
+
/>
|
|
291
|
+
</div>
|
|
292
|
+
<!-- hero media -->
|
|
293
|
+
<HeroMedia
|
|
294
|
+
v-if="
|
|
295
|
+
!heroEmpty &&
|
|
296
|
+
!heroInline &&
|
|
297
|
+
data?.hero?.length &&
|
|
298
|
+
(data.hero[0].blockType === 'HeroImageBlock' || data.hero[0].blockType === 'VideoBlock')
|
|
299
|
+
"
|
|
300
|
+
:image="data.hero[0].image"
|
|
301
|
+
:video="data.hero[0].video"
|
|
302
|
+
:display-caption="false"
|
|
303
|
+
:caption="data.hero[0].caption"
|
|
304
|
+
:credit="data.hero[0].credit"
|
|
305
|
+
:constrain="data.heroConstrain"
|
|
306
|
+
/>
|
|
307
|
+
<LayoutHelper
|
|
308
|
+
v-else-if="!heroEmpty && heroInline && data.hero?.length"
|
|
309
|
+
class="lg:mb-14 mb-10"
|
|
310
|
+
>
|
|
311
|
+
<HeroInlineMedia
|
|
312
|
+
:hero-blocks="data.hero"
|
|
313
|
+
:constrain="data.heroConstrain"
|
|
314
|
+
/>
|
|
315
|
+
</LayoutHelper>
|
|
316
|
+
|
|
317
|
+
<MetaPanel
|
|
318
|
+
button="Info for Teachers"
|
|
319
|
+
theme="stars"
|
|
320
|
+
:class="{ 'mb-10 lg:mb-14': true }"
|
|
321
|
+
:primary-subject="data.primarySubject"
|
|
322
|
+
:additional-subjects="data.additionalSubjects"
|
|
323
|
+
:time="data.customTime ? { time: data.customTime } : data.time"
|
|
324
|
+
:standards="data.standards"
|
|
325
|
+
:negative-top="!heroInline && !heroEmpty"
|
|
326
|
+
>
|
|
327
|
+
<template #metaInfo>
|
|
328
|
+
<div :class="data?.standards ? 'border-b border-gray-light-mid' : ''">
|
|
329
|
+
<div class="py-6 lg:py-8">
|
|
330
|
+
<MetaPanelItems :grade-levels="data?.gradeLevels" />
|
|
331
|
+
<div
|
|
332
|
+
v-if="data.lesson"
|
|
333
|
+
class="mt-8 font-bold text-body-s"
|
|
334
|
+
>
|
|
335
|
+
Want to teach this?
|
|
336
|
+
<BaseLink
|
|
337
|
+
class="font-normal inline text-action underline hover:text-action-dark cursor-pointer"
|
|
338
|
+
variant="none"
|
|
339
|
+
:to="data.lesson.url"
|
|
340
|
+
>
|
|
341
|
+
View the Lesson Plan
|
|
342
|
+
</BaseLink>
|
|
343
|
+
</div>
|
|
344
|
+
</div>
|
|
345
|
+
</div>
|
|
346
|
+
</template>
|
|
347
|
+
</MetaPanel>
|
|
348
|
+
|
|
349
|
+
<NavJumpMenu
|
|
350
|
+
ref="PageEduStudentProjectJumpMenu"
|
|
351
|
+
:title="data.title"
|
|
352
|
+
:blocks="consolidatedBlocks"
|
|
353
|
+
dropdown-text="In this project"
|
|
354
|
+
/>
|
|
355
|
+
|
|
356
|
+
<template
|
|
357
|
+
v-for="(value, _key) in consolidatedSections"
|
|
358
|
+
:key="_key"
|
|
359
|
+
>
|
|
360
|
+
<BlockStreamfield
|
|
361
|
+
v-if="value.type === 'streamfield'"
|
|
362
|
+
:data="value.blocks"
|
|
363
|
+
/>
|
|
364
|
+
<PageEduStudentProjectSection
|
|
365
|
+
v-else
|
|
366
|
+
:heading="value.heading"
|
|
367
|
+
:blocks="value.blocks"
|
|
368
|
+
:steps="value.steps"
|
|
369
|
+
:steps-numbering="data.stepsNumbering"
|
|
370
|
+
:text="value.text"
|
|
371
|
+
:image="value.image"
|
|
372
|
+
/>
|
|
373
|
+
</template>
|
|
374
|
+
|
|
375
|
+
<!-- streamfield blocks -->
|
|
376
|
+
<BlockStreamfield
|
|
377
|
+
v-if="data.body?.length"
|
|
378
|
+
:data="data.body"
|
|
379
|
+
/>
|
|
380
|
+
|
|
381
|
+
<!-- related links -->
|
|
382
|
+
<LayoutHelper
|
|
383
|
+
v-if="data.relatedLinks && data.relatedLinks.length"
|
|
384
|
+
indent="col-3"
|
|
385
|
+
class="lg:my-18 my-10"
|
|
386
|
+
>
|
|
387
|
+
<BlockRelatedLinks :data="data.relatedLinks[0]" />
|
|
388
|
+
</LayoutHelper>
|
|
389
|
+
|
|
390
|
+
<!-- related content -->
|
|
391
|
+
<BlockLinkCarousel
|
|
392
|
+
item-type="cards"
|
|
393
|
+
class="lg:my-24 my-12 print:px-4"
|
|
394
|
+
:heading="data.relatedContentHeading || 'Related Projects'"
|
|
395
|
+
:items="data.relatedContent"
|
|
396
|
+
/>
|
|
397
|
+
|
|
398
|
+
<LayoutHelper
|
|
399
|
+
v-if="data.authors?.length"
|
|
400
|
+
indent="col-3"
|
|
401
|
+
>
|
|
402
|
+
<AboutTheAuthor :authors="data.authors" />
|
|
403
|
+
</LayoutHelper>
|
|
404
|
+
|
|
405
|
+
<LayoutHelper
|
|
406
|
+
v-if="data.lastPublishedAt"
|
|
407
|
+
indent="col-3"
|
|
408
|
+
class="lg:my-18 my-10"
|
|
409
|
+
>
|
|
410
|
+
<p class="border-t border-gray-light-mid pt-8">
|
|
411
|
+
<strong>Lesson Last Updated:</strong>
|
|
412
|
+
{{
|
|
413
|
+
// @ts-ignore
|
|
414
|
+
$filters.displayDate(data.lastPublishedAt)
|
|
415
|
+
}}
|
|
416
|
+
</p>
|
|
417
|
+
</LayoutHelper>
|
|
418
|
+
</div>
|
|
419
|
+
</template>
|