@asd20/ui 3.2.977 → 3.2.978
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/package.json +1 -1
- package/src/components/atoms/Asd20Icon/index.stories.js +1 -2
- package/src/components/organisms/Asd20AccessibilityIssueModal/index.stories.js +20 -0
- package/src/components/organisms/Asd20AccessibilityIssueModal/index.vue +211 -0
- package/src/components/organisms/Asd20PageContent/index.vue +1 -0
- package/src/components/templates/Asd20WayfindingAccessibilityTemplate/index.stories.js +68 -0
- package/src/components/templates/Asd20WayfindingAccessibilityTemplate/index.vue +337 -0
- package/src/data/page-queries/landing-page-query-result.json +1 -1
- package/src/helpers/sendAccessibilityIssue.js +47 -0
- /package/src/components/atoms/icons/{Asd20AccessiblitySvg.vue → Asd20AccessibilitySvg.vue} +0 -0
package/package.json
CHANGED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { storiesOf } from '@storybook/vue'
|
|
2
|
+
import Asd20AccessibilityIssueModal from '.'
|
|
3
|
+
|
|
4
|
+
const info = {
|
|
5
|
+
summary: 'Asd20AccessibilityIssueModal',
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const wrapper = {
|
|
9
|
+
components: { Asd20AccessibilityIssueModal },
|
|
10
|
+
data: () => ({}),
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
storiesOf('Organisms - Asd20AccessibilityIssueModal', module).add(
|
|
14
|
+
'Default',
|
|
15
|
+
() => ({
|
|
16
|
+
...wrapper,
|
|
17
|
+
template: `<Asd20AccessibilityIssueModal :open="true" recipient-id="14776"></Asd20AccessibilityIssueModal>`,
|
|
18
|
+
}),
|
|
19
|
+
{ info }
|
|
20
|
+
)
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<asd20-modal
|
|
3
|
+
:open="open"
|
|
4
|
+
title="Report an Accessibility Issue"
|
|
5
|
+
icon="accessibility"
|
|
6
|
+
dismissable
|
|
7
|
+
windowed
|
|
8
|
+
class="asd20-accessibility-issue-modal"
|
|
9
|
+
@dismiss="$emit('dismiss')"
|
|
10
|
+
>
|
|
11
|
+
<Asd20Viewport scrollable>
|
|
12
|
+
<div v-if="submissionSuccess" class="submission-success">
|
|
13
|
+
<p style="text-align: center; font-weight: bold; font-size: 1.1rem;">
|
|
14
|
+
Thank you! Your issue has been submitted.
|
|
15
|
+
</p>
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
<template v-else>
|
|
19
|
+
<asd20-text-input
|
|
20
|
+
id="firstName"
|
|
21
|
+
label="First Name"
|
|
22
|
+
required
|
|
23
|
+
v-model="form.firstName"
|
|
24
|
+
@validated="validationErrors.firstName = $event"
|
|
25
|
+
/>
|
|
26
|
+
<asd20-text-input
|
|
27
|
+
id="lastName"
|
|
28
|
+
label="Last Name"
|
|
29
|
+
required
|
|
30
|
+
v-model="form.lastName"
|
|
31
|
+
@validated="validationErrors.lastName = $event"
|
|
32
|
+
/>
|
|
33
|
+
<asd20-text-input
|
|
34
|
+
id="email"
|
|
35
|
+
label="Email Address"
|
|
36
|
+
type="email"
|
|
37
|
+
required
|
|
38
|
+
:validator="validateEmailAddress"
|
|
39
|
+
v-model="form.email"
|
|
40
|
+
@validated="validationErrors.email = $event"
|
|
41
|
+
/>
|
|
42
|
+
<asd20-text-input
|
|
43
|
+
id="phone"
|
|
44
|
+
label="Phone Number"
|
|
45
|
+
v-model="form.phone"
|
|
46
|
+
/>
|
|
47
|
+
<asd20-text-input
|
|
48
|
+
id="address"
|
|
49
|
+
label="Mailing Address"
|
|
50
|
+
v-model="form.address"
|
|
51
|
+
/>
|
|
52
|
+
<asd20-text-input
|
|
53
|
+
id="organization"
|
|
54
|
+
label="Organization"
|
|
55
|
+
v-model="form.organization"
|
|
56
|
+
/>
|
|
57
|
+
<asd20-text-area-input
|
|
58
|
+
id="issue"
|
|
59
|
+
label="Describe the Issue"
|
|
60
|
+
help-text="<ul style='margin: 0 0 0.5rem 1rem; font-size: 0.75rem !important;'>
|
|
61
|
+
<li>Please specify the exact URL, program, service, or digital asset you had a problem with.</li>
|
|
62
|
+
<li>Please provide as much detail as possible, including the nature of the accessibility barrier, the date and time it occurred, any assistive technology you were using, or the nature of the program or service being denied.</li>
|
|
63
|
+
<li>Please describe what you believe should be done to resolve the issue.</li>
|
|
64
|
+
</ul>"
|
|
65
|
+
required
|
|
66
|
+
v-model="form.issue"
|
|
67
|
+
@validated="validationErrors.issue = $event"
|
|
68
|
+
/>
|
|
69
|
+
<asd20-button
|
|
70
|
+
label="Submit Issue"
|
|
71
|
+
:disabled="!isValid || sending"
|
|
72
|
+
@click="sendAccessibilityIssue"
|
|
73
|
+
horizontal
|
|
74
|
+
centered
|
|
75
|
+
bordered
|
|
76
|
+
/>
|
|
77
|
+
<!-- <vue-recaptcha
|
|
78
|
+
sitekey="6LfidKoUAAAAAFqr3QEbia3jIkecsZyxBYlMvWrX"
|
|
79
|
+
:loadRecaptchaScript="true"
|
|
80
|
+
size="invisible"
|
|
81
|
+
@verify="captchaVerified"
|
|
82
|
+
>
|
|
83
|
+
<asd20-button
|
|
84
|
+
v-show="isValid && !sending"
|
|
85
|
+
label="Submit Issue"
|
|
86
|
+
horizontal
|
|
87
|
+
/>
|
|
88
|
+
</vue-recaptcha> -->
|
|
89
|
+
<asd20-spinner size="sm" v-if="sending" />
|
|
90
|
+
</template>
|
|
91
|
+
</Asd20Viewport>
|
|
92
|
+
</asd20-modal>
|
|
93
|
+
</template>
|
|
94
|
+
|
|
95
|
+
<script>
|
|
96
|
+
import Asd20Modal from '../../molecules/Asd20Modal'
|
|
97
|
+
import Asd20TextInput from '../../molecules/Asd20TextInput'
|
|
98
|
+
import Asd20TextAreaInput from '../../molecules/Asd20TextAreaInput'
|
|
99
|
+
import Asd20Viewport from '../../atoms/Asd20Viewport'
|
|
100
|
+
import Asd20Spinner from '../../atoms/Asd20Spinner'
|
|
101
|
+
import VueRecaptcha from 'vue-recaptcha'
|
|
102
|
+
import Asd20Button from '../../atoms/Asd20Button'
|
|
103
|
+
|
|
104
|
+
// import sendAccessibilityIssue from '../../../helpers/sendAccessibilityIssue.js'
|
|
105
|
+
|
|
106
|
+
export default {
|
|
107
|
+
name: 'Asd20AccessibilityIssueModal',
|
|
108
|
+
components: {
|
|
109
|
+
Asd20Modal,
|
|
110
|
+
Asd20TextInput,
|
|
111
|
+
Asd20TextAreaInput,
|
|
112
|
+
Asd20Viewport,
|
|
113
|
+
Asd20Spinner,
|
|
114
|
+
VueRecaptcha,
|
|
115
|
+
Asd20Button,
|
|
116
|
+
},
|
|
117
|
+
props: {
|
|
118
|
+
open: { type: Boolean, default: false },
|
|
119
|
+
},
|
|
120
|
+
data() {
|
|
121
|
+
return {
|
|
122
|
+
sending: false,
|
|
123
|
+
submissionSuccess: false,
|
|
124
|
+
form: {
|
|
125
|
+
firstName: '',
|
|
126
|
+
lastName: '',
|
|
127
|
+
email: '',
|
|
128
|
+
phone: '',
|
|
129
|
+
address: '',
|
|
130
|
+
organization: '',
|
|
131
|
+
issue: '',
|
|
132
|
+
},
|
|
133
|
+
validationErrors: {
|
|
134
|
+
firstName: [],
|
|
135
|
+
lastName: [],
|
|
136
|
+
email: [],
|
|
137
|
+
issue: [],
|
|
138
|
+
},
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
computed: {
|
|
142
|
+
isValid() {
|
|
143
|
+
return Object.values(this.validationErrors).every(e => e.length === 0)
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
methods: {
|
|
147
|
+
validateEmailAddress({ value, validationErrors }) {
|
|
148
|
+
const pattern = /^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/
|
|
149
|
+
if (!pattern.test(value)) {
|
|
150
|
+
validationErrors.push('A valid email address is required')
|
|
151
|
+
}
|
|
152
|
+
return validationErrors
|
|
153
|
+
},
|
|
154
|
+
captchaVerified(token) {
|
|
155
|
+
// Placeholder: reCAPTCHA not functional yet
|
|
156
|
+
this.submitIssue()
|
|
157
|
+
},
|
|
158
|
+
async sendAccessibilityIssue() {
|
|
159
|
+
if (!this.isValid || !this.$sendAccessibilityIssue) return
|
|
160
|
+
this.sending = true
|
|
161
|
+
|
|
162
|
+
try {
|
|
163
|
+
await this.$sendAccessibilityIssue(
|
|
164
|
+
this.form,
|
|
165
|
+
this.$config.happyfoxEndpoint,
|
|
166
|
+
this.$config.happyfoxApiKey,
|
|
167
|
+
this.$config.happyfoxAuthCode
|
|
168
|
+
)
|
|
169
|
+
this.submissionSuccess = true
|
|
170
|
+
|
|
171
|
+
// Wait 2 seconds, then close the modal
|
|
172
|
+
setTimeout(() => {
|
|
173
|
+
this.submissionSuccess = false
|
|
174
|
+
this.$emit('dismiss')
|
|
175
|
+
}, 2000)
|
|
176
|
+
} catch (e) {
|
|
177
|
+
console.error('Accessibility issue submission failed:', e.message || e)
|
|
178
|
+
alert(
|
|
179
|
+
'Something went wrong while submitting the form. Please try again later.'
|
|
180
|
+
)
|
|
181
|
+
} finally {
|
|
182
|
+
this.sending = false
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
}
|
|
187
|
+
</script>
|
|
188
|
+
|
|
189
|
+
<style lang="scss" scoped>
|
|
190
|
+
@import '../../../design/_mixins.scss';
|
|
191
|
+
@import '../../../design/_variables.scss';
|
|
192
|
+
|
|
193
|
+
.asd20-accessibility-issue-modal {
|
|
194
|
+
&::v-deep .asd20-modal__content .asd20-viewport {
|
|
195
|
+
padding: space(1);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
@media (min-width: 1024px) {
|
|
200
|
+
.asd20-accessibility-issue-modal {
|
|
201
|
+
&::v-deep .asd20-modal__content .asd20-viewport {
|
|
202
|
+
padding: space(1);
|
|
203
|
+
}
|
|
204
|
+
&::v-deep .asd20-modal {
|
|
205
|
+
margin-top: auto;
|
|
206
|
+
margin-bottom: auto;
|
|
207
|
+
max-width: 40vw;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
</style>
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { storiesOf } from '@storybook/vue'
|
|
2
|
+
import { withKnobs, boolean } from '@storybook/addon-knobs'
|
|
3
|
+
|
|
4
|
+
import mockPageMixin from '../../../mixins/mockPageMixin'
|
|
5
|
+
|
|
6
|
+
import Asd20WayfindingAccessibilityTemplate from '.'
|
|
7
|
+
import pageQueryResult from '../../../data/page-queries/landing-page-query-result.json'
|
|
8
|
+
import notifications from '../../../data/messages/notifications'
|
|
9
|
+
|
|
10
|
+
const info = {
|
|
11
|
+
summary: 'Wayfinding Accessibility Page Template',
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const wrapper = {
|
|
15
|
+
mixins: [mockPageMixin],
|
|
16
|
+
components: {
|
|
17
|
+
Asd20WayfindingAccessibilityTemplate,
|
|
18
|
+
},
|
|
19
|
+
watch: {
|
|
20
|
+
languageCode(newValue, oldValue) {
|
|
21
|
+
console.log(newValue, oldValue)
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
data: () => ({ pageQueryResult, languageCode: 'es' }),
|
|
26
|
+
|
|
27
|
+
computed: {
|
|
28
|
+
activeNotificationsByType() {
|
|
29
|
+
const empty = {
|
|
30
|
+
inline: [],
|
|
31
|
+
banner: [],
|
|
32
|
+
floating: [],
|
|
33
|
+
status: [],
|
|
34
|
+
}
|
|
35
|
+
return boolean('Show Notifications', true)
|
|
36
|
+
? notifications || empty
|
|
37
|
+
: empty
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const stories = storiesOf(
|
|
44
|
+
'Templates - Asd20WayfindingAccessibilityTemplate',
|
|
45
|
+
module
|
|
46
|
+
)
|
|
47
|
+
stories.addDecorator(withKnobs)
|
|
48
|
+
|
|
49
|
+
stories.add(
|
|
50
|
+
'Default',
|
|
51
|
+
() => ({
|
|
52
|
+
...wrapper,
|
|
53
|
+
template: `
|
|
54
|
+
<Asd20WayfindingAccessibilityTemplate
|
|
55
|
+
v-bind="templateProps"
|
|
56
|
+
:menu-open.sync="menuOpen"
|
|
57
|
+
:search-open.sync="searchOpen"
|
|
58
|
+
|
|
59
|
+
@announcements-in-view="loadAnnouncements"
|
|
60
|
+
@stories-in-view="loadStories"
|
|
61
|
+
@events-in-view="loadEvents"
|
|
62
|
+
@files-in-view="loadFiles"
|
|
63
|
+
@people-in-view="loadPeople"
|
|
64
|
+
:languageCode.sync="languageCode"
|
|
65
|
+
/>`,
|
|
66
|
+
}),
|
|
67
|
+
{ info }
|
|
68
|
+
)
|
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="asd20-template-wayfinding-accessibility">
|
|
3
|
+
<!-- Skip Nav -->
|
|
4
|
+
<asd20-skip-to></asd20-skip-to>
|
|
5
|
+
|
|
6
|
+
<!-- Site Navigation -->
|
|
7
|
+
<asd20-site-navigation
|
|
8
|
+
:navigation="navigation"
|
|
9
|
+
:action-items="actionItems"
|
|
10
|
+
@update:menuOpen="$emit('update:menuOpen', $event)"
|
|
11
|
+
:menu-open="menuOpen"
|
|
12
|
+
@update:searchOpen="$emit('update:searchOpen', $event)"
|
|
13
|
+
:search-open="searchOpen"
|
|
14
|
+
:organization="organization"
|
|
15
|
+
:organization-options="organizationOptions"
|
|
16
|
+
>
|
|
17
|
+
</asd20-site-navigation>
|
|
18
|
+
|
|
19
|
+
<!-- Banner Notifications -->
|
|
20
|
+
<client-only>
|
|
21
|
+
<asd20-notification-group
|
|
22
|
+
:notifications="activeNotificationsByType.banner"
|
|
23
|
+
group-type="banner"
|
|
24
|
+
@dismiss="$emit('dismiss-notification', $event)"
|
|
25
|
+
@toggle-all="$emit('toggle-all')"
|
|
26
|
+
></asd20-notification-group>
|
|
27
|
+
</client-only>
|
|
28
|
+
|
|
29
|
+
<!-- Page Header -->
|
|
30
|
+
<asd20-page-header
|
|
31
|
+
id="page-header"
|
|
32
|
+
v-show="pageHeaderContent"
|
|
33
|
+
v-bind="pageHeaderContent"
|
|
34
|
+
:organization="organization"
|
|
35
|
+
:organization-options="organizationOptions"
|
|
36
|
+
:languageCode="languageCode"
|
|
37
|
+
v-on="$listeners"
|
|
38
|
+
:breadcrumb-links="breadcrumbLinks"
|
|
39
|
+
>
|
|
40
|
+
<!-- Floating Notifications -->
|
|
41
|
+
<template slot="top">
|
|
42
|
+
<client-only>
|
|
43
|
+
<asd20-notification-group
|
|
44
|
+
class="asd20-notification-group--floating"
|
|
45
|
+
:notifications="activeNotificationsByType.floating"
|
|
46
|
+
:total-dismissed-notifications="totalDismissedNotifications"
|
|
47
|
+
group-type="floating"
|
|
48
|
+
@dismiss="$emit('dismiss-notification', $event)"
|
|
49
|
+
@toggle-all="$emit('toggle-all')"
|
|
50
|
+
></asd20-notification-group>
|
|
51
|
+
</client-only>
|
|
52
|
+
</template>
|
|
53
|
+
<!-- <asd20-breadcrumb slot="top" :links="breadcrumbLinks"></asd20-breadcrumb> -->
|
|
54
|
+
</asd20-page-header>
|
|
55
|
+
|
|
56
|
+
<!-- Inline-Notifications -->
|
|
57
|
+
<template>
|
|
58
|
+
<client-only>
|
|
59
|
+
<asd20-notification-group
|
|
60
|
+
class="asd20-notification-group--inline"
|
|
61
|
+
:notifications="activeNotificationsByType.inline"
|
|
62
|
+
group-type="inline"
|
|
63
|
+
@dismiss="$emit('dismiss-notification', $event)"
|
|
64
|
+
@toggle-all="$emit('toggle-all')"
|
|
65
|
+
></asd20-notification-group>
|
|
66
|
+
</client-only>
|
|
67
|
+
</template>
|
|
68
|
+
|
|
69
|
+
<!-- Page Content -->
|
|
70
|
+
<asd20-page-content
|
|
71
|
+
class="intro-message"
|
|
72
|
+
:primary-messages="primaryMessage"
|
|
73
|
+
omit-detail-links
|
|
74
|
+
omit-calls-to-action
|
|
75
|
+
/>
|
|
76
|
+
<asd20-page-content
|
|
77
|
+
:class="wayFindingPrimaryMessages.length > 3 ? 'limit-message-width' : ''"
|
|
78
|
+
:primary-messages="wayFindingPrimaryMessages"
|
|
79
|
+
:secondary-messages="secondaryMessages"
|
|
80
|
+
omit-body-content
|
|
81
|
+
omit-calls-to-action
|
|
82
|
+
grid
|
|
83
|
+
/>
|
|
84
|
+
|
|
85
|
+
<!-- Feed Section -->
|
|
86
|
+
<asd20-feeds-section
|
|
87
|
+
:announcements="announcements"
|
|
88
|
+
:announcements-feed-props="announcementsFeedProps"
|
|
89
|
+
@announcements-in-view="$emit('announcements-in-view')"
|
|
90
|
+
:stories="stories"
|
|
91
|
+
:stories-feed-props="storiesFeedProps"
|
|
92
|
+
@stories-in-view="$emit('stories-in-view')"
|
|
93
|
+
:events="events"
|
|
94
|
+
:events-feed-props="eventsFeedProps"
|
|
95
|
+
@events-in-view="$emit('events-in-view')"
|
|
96
|
+
:organization="organization"
|
|
97
|
+
:organization-options="organizationOptions"
|
|
98
|
+
></asd20-feeds-section>
|
|
99
|
+
|
|
100
|
+
<!-- Photos & Videos -->
|
|
101
|
+
<asd20-media-section
|
|
102
|
+
v-if="firstMessage.images.length > 1 || firstMessage.videos.length"
|
|
103
|
+
:images="this.firstMessage.images || []"
|
|
104
|
+
:videos="this.firstMessage.videos || []"
|
|
105
|
+
>
|
|
106
|
+
</asd20-media-section>
|
|
107
|
+
|
|
108
|
+
<!-- Bottom Widgets -->
|
|
109
|
+
<asd20-widgets-section
|
|
110
|
+
v-if="
|
|
111
|
+
widgetsSectionProps.footer ||
|
|
112
|
+
widgetsSectionProps.sidebar ||
|
|
113
|
+
$slots.widgets
|
|
114
|
+
"
|
|
115
|
+
:related-links="relatedLinks"
|
|
116
|
+
v-bind="{ ...widgetsSectionProps.footer, ...widgetsSectionProps.sidebar }"
|
|
117
|
+
@events-in-view="$emit('events-in-view')"
|
|
118
|
+
@files-in-view="$emit('files-in-view')"
|
|
119
|
+
@people-in-view="$emit('people-in-view')"
|
|
120
|
+
full
|
|
121
|
+
><slot name="widgets"
|
|
122
|
+
/></asd20-widgets-section>
|
|
123
|
+
|
|
124
|
+
<slot name="before-footer" />
|
|
125
|
+
|
|
126
|
+
<!-- Quick Links -->
|
|
127
|
+
<asd20-quicklinks-menu slot="before-footer" :quick-links="quickLinks">
|
|
128
|
+
<slot name="quicklinks-menu" />
|
|
129
|
+
</asd20-quicklinks-menu>
|
|
130
|
+
|
|
131
|
+
<!-- Footer -->
|
|
132
|
+
<asd20-page-footer
|
|
133
|
+
:organization="organization"
|
|
134
|
+
:socialLinks="socialLinks"
|
|
135
|
+
:disclosureLinks="disclosureLinks"
|
|
136
|
+
:websiteLogoProps="websiteLogoProps"
|
|
137
|
+
:websiteLogoProps2="websiteLogoProps2"
|
|
138
|
+
>
|
|
139
|
+
<slot name="page-footer" />
|
|
140
|
+
</asd20-page-footer>
|
|
141
|
+
<Asd20AccessibilityIssueModal
|
|
142
|
+
v-show="modalVisible"
|
|
143
|
+
:open="modalOpen"
|
|
144
|
+
@dismiss="modalOpen = false"
|
|
145
|
+
/>
|
|
146
|
+
</div>
|
|
147
|
+
</template>
|
|
148
|
+
|
|
149
|
+
<script>
|
|
150
|
+
// Components
|
|
151
|
+
import Asd20SkipTo from '../../../components/atoms/Asd20SkipTo'
|
|
152
|
+
import Asd20PageHeader from '../../../components/organisms/Asd20PageHeader'
|
|
153
|
+
|
|
154
|
+
import Asd20SiteNavigation from '../../../components/organisms/Asd20SiteNavigation'
|
|
155
|
+
import Asd20PageContent from '../../../components/organisms/Asd20PageContent'
|
|
156
|
+
|
|
157
|
+
import Asd20WidgetsSection from '../../../components/organisms/Asd20WidgetsSection'
|
|
158
|
+
import Asd20FeedsSection from '../../../components/organisms/Asd20FeedsSection'
|
|
159
|
+
import Asd20MediaSection from '../../../components/organisms/Asd20MediaSection'
|
|
160
|
+
import Asd20AccessibilityIssueModal from '../../../components/organisms/Asd20AccessibilityIssueModal'
|
|
161
|
+
import Asd20PageFooter from '../../../components/organisms/Asd20PageFooter'
|
|
162
|
+
import Asd20QuicklinksMenu from '../../../components/organisms/Asd20QuicklinksMenu'
|
|
163
|
+
import Asd20NotificationGroup from '../../../components/organisms/Asd20NotificationGroup'
|
|
164
|
+
|
|
165
|
+
// import Intersect from 'vue-intersect'
|
|
166
|
+
|
|
167
|
+
// Mixins
|
|
168
|
+
import pageTemplateMixin from '../../../mixins/pageTemplateMixin'
|
|
169
|
+
|
|
170
|
+
export default {
|
|
171
|
+
name: 'Asd20WayfindingAccessibilityTemplate',
|
|
172
|
+
mixins: [pageTemplateMixin],
|
|
173
|
+
components: {
|
|
174
|
+
Asd20PageContent,
|
|
175
|
+
Asd20SkipTo,
|
|
176
|
+
Asd20PageHeader,
|
|
177
|
+
Asd20PageFooter,
|
|
178
|
+
Asd20SiteNavigation,
|
|
179
|
+
Asd20WidgetsSection,
|
|
180
|
+
Asd20FeedsSection,
|
|
181
|
+
Asd20NotificationGroup,
|
|
182
|
+
Asd20QuicklinksMenu,
|
|
183
|
+
Asd20MediaSection,
|
|
184
|
+
Asd20AccessibilityIssueModal,
|
|
185
|
+
},
|
|
186
|
+
data() {
|
|
187
|
+
return {
|
|
188
|
+
modalVisible: false,
|
|
189
|
+
modalOpen: false,
|
|
190
|
+
}
|
|
191
|
+
},
|
|
192
|
+
mounted() {
|
|
193
|
+
this.$nextTick(() => {
|
|
194
|
+
const btn = document.querySelector('[data-trigger-accessibility-modal]')
|
|
195
|
+
if (btn) {
|
|
196
|
+
btn.addEventListener('click', () => {
|
|
197
|
+
this.modalVisible = true
|
|
198
|
+
this.$nextTick(() => {
|
|
199
|
+
this.modalOpen = true
|
|
200
|
+
})
|
|
201
|
+
})
|
|
202
|
+
}
|
|
203
|
+
})
|
|
204
|
+
},
|
|
205
|
+
computed: {
|
|
206
|
+
wayFindingPrimaryMessages() {
|
|
207
|
+
// wayfinding page
|
|
208
|
+
return (
|
|
209
|
+
this.messages
|
|
210
|
+
// Remove the first message, limit
|
|
211
|
+
.slice(
|
|
212
|
+
1,
|
|
213
|
+
Math.min(this.messages.length, this.primaryMessageLimit + 1)
|
|
214
|
+
)
|
|
215
|
+
)
|
|
216
|
+
},
|
|
217
|
+
primaryMessage() {
|
|
218
|
+
const introMessage = this.primaryMessages.slice(0, 1)
|
|
219
|
+
if (introMessage[0].bodyHtml === '' || null) return
|
|
220
|
+
return introMessage
|
|
221
|
+
},
|
|
222
|
+
},
|
|
223
|
+
}
|
|
224
|
+
</script>
|
|
225
|
+
|
|
226
|
+
<style lang="scss">
|
|
227
|
+
@import '../../../design/_variables.scss';
|
|
228
|
+
@import '../../../design/_mixins.scss';
|
|
229
|
+
@import '../../../design/_typography.scss';
|
|
230
|
+
@import '../../../design/_template.scss';
|
|
231
|
+
@import '../../../design/_print.scss';
|
|
232
|
+
@import '../../../design/tokens.css';
|
|
233
|
+
|
|
234
|
+
.asd20-template-wayfinding-accessibility {
|
|
235
|
+
@include typography;
|
|
236
|
+
@include template;
|
|
237
|
+
display: flex;
|
|
238
|
+
flex-direction: column;
|
|
239
|
+
flex-grow: 1;
|
|
240
|
+
flex-shrink: 0;
|
|
241
|
+
overflow: hidden;
|
|
242
|
+
margin-top: space(2.25);
|
|
243
|
+
.asd20-notification-group--floating {
|
|
244
|
+
position: absolute;
|
|
245
|
+
top: space(2.0375);
|
|
246
|
+
// .bell {
|
|
247
|
+
// box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.125) !important;
|
|
248
|
+
// svg {
|
|
249
|
+
// fill: var(--color__accent) !important;
|
|
250
|
+
// }
|
|
251
|
+
// span {
|
|
252
|
+
// background: var(--color__accent) !important;
|
|
253
|
+
// top: inherit !important;
|
|
254
|
+
// right: inherit !important;
|
|
255
|
+
// width: 1.2rem !important;
|
|
256
|
+
// height: 1.2rem !important;
|
|
257
|
+
// font-size: 0.75rem !important;
|
|
258
|
+
// }
|
|
259
|
+
// }
|
|
260
|
+
}
|
|
261
|
+
.asd20-notification-group--inline {
|
|
262
|
+
margin-top: space(2) !important;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
.intro-message {
|
|
266
|
+
.primary-messaging-section {
|
|
267
|
+
justify-content: center;
|
|
268
|
+
margin-top: space(1) !important;
|
|
269
|
+
padding: space(1) space(2) !important;
|
|
270
|
+
.asd20-messaging {
|
|
271
|
+
border-top: space(0.25) solid var(--color__tertiary);
|
|
272
|
+
border-bottom: space(0.25) solid var(--color__tertiary);
|
|
273
|
+
padding: space(1) 0;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
p {
|
|
278
|
+
// font-family: var(--website-typography__font-family-headlines);
|
|
279
|
+
font-size: 1rem !important;
|
|
280
|
+
line-height: 1.5;
|
|
281
|
+
font-family: var(--website-typography__font-family-headlines);
|
|
282
|
+
}
|
|
283
|
+
h2 {
|
|
284
|
+
@include asd20-font(
|
|
285
|
+
1.5,
|
|
286
|
+
var(--website-typography__font-family-headlines),
|
|
287
|
+
1.2,
|
|
288
|
+
700
|
|
289
|
+
);
|
|
290
|
+
font-family: var(--website-typography__font-family-headlines);
|
|
291
|
+
// font-size: 36px !important;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
// .asd20-messaging {
|
|
295
|
+
// padding-bottom: space(2);
|
|
296
|
+
// border-bottom: 10px solid var(--color__tertiary);
|
|
297
|
+
// }
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
@media (min-width: 1024px) {
|
|
301
|
+
.asd20-template-wayfinding-accessibility {
|
|
302
|
+
.asd20-notification-group--floating {
|
|
303
|
+
position: absolute;
|
|
304
|
+
top: space(1);
|
|
305
|
+
// .bell {
|
|
306
|
+
// span {
|
|
307
|
+
// background: var(--color__accent);
|
|
308
|
+
// top: -0.6em !important;
|
|
309
|
+
// right: -0.6em !important;
|
|
310
|
+
// }
|
|
311
|
+
// }
|
|
312
|
+
}
|
|
313
|
+
@include template-desktop;
|
|
314
|
+
margin-left: space(3);
|
|
315
|
+
margin-top: 0;
|
|
316
|
+
.asd20-page-content {
|
|
317
|
+
margin-top: space(0);
|
|
318
|
+
}
|
|
319
|
+
// .intro-message {
|
|
320
|
+
// width: 90%;
|
|
321
|
+
// }
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
@media (min-width: 1790px) {
|
|
326
|
+
.limit-message-width {
|
|
327
|
+
.primary-messaging-section,
|
|
328
|
+
.secondary-messaging-section {
|
|
329
|
+
.asd20-messaging {
|
|
330
|
+
flex: 1 1 var(--minimum-column-width);
|
|
331
|
+
margin: var(--gutter) !important;
|
|
332
|
+
max-width: 30% !important;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
</style>
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
"id": "4fe4dc65-0d61-497f-8596-e4c5d156bf71",
|
|
81
81
|
"title": "Supports for Academic Success",
|
|
82
82
|
"summary": "Academy District 20 provides a host of services so all students have the tools they need to achieve academic success.",
|
|
83
|
-
"bodyHtml": "<h2>Overview</h2><p>Each Academy District 20 school has at least one special education teacher and speech/language pathologist. Students may also receive supports from school social workers, school psychologists, school nurses and occupational and physical therapists. </p><p>Our special education staff members work with students and their families in a variety of ways such as: completing assessments, participating in the development of Individual Education Plans (IEPs) and providing specialized support services. </p><p>Special Education staff meet the state standards for licensed teachers and/or special service providers through the Colorado Department of Education. </p><h2>Inclusion at Academy District 20</h2><p>Inclusion is a child-centered, collaborative process that focuses on the unique needs of each student as an equally valued member of the school community. Inclusion gives each student authentic access to the standards driven curriculum and social community through meaningful instruction and interaction supported by the intentional allocation of time and resources.</p><p>This includes the practice of educating all students together to the maximum extent appropriate with the long -range goal of independence, and participation in and contribution to the community.</p>",
|
|
83
|
+
"bodyHtml": "<h2>Overview</h2><p>Each Academy District 20 school has at least one special education teacher and speech/language pathologist. Students may also receive supports from school social workers, school psychologists, school nurses and occupational and physical therapists. </p><p>Our special education staff members work with students and their families in a variety of ways such as: completing assessments, participating in the development of Individual Education Plans (IEPs) and providing specialized support services. </p><p>Special Education staff meet the state standards for licensed teachers and/or special service providers through the Colorado Department of Education. </p><h2>Inclusion at Academy District 20</h2><p>Inclusion is a child-centered, collaborative process that focuses on the unique needs of each student as an equally valued member of the school community. Inclusion gives each student authentic access to the standards driven curriculum and social community through meaningful instruction and interaction supported by the intentional allocation of time and resources.</p><p>This includes the practice of educating all students together to the maximum extent appropriate with the long -range goal of independence, and participation in and contribution to the community.</p><button class='asd20-button' data-trigger-accessibility-modal style='margin: 1rem auto; padding: var(--space-1, 1em); background-color: var(--website-page__background-color, #f5f5f5); color: var(--website-page__title-color, #333); font-family: var(--website-typography__font-family-headlines; font-size: 1rem; font-weight: bold; border: 2px solid var(--color__primary); cursor: pointer; display: flex; justify-content: space-between; align-items: center;'>Notify Us of an Accessibility Issue</button>",
|
|
84
84
|
"status": "Published",
|
|
85
85
|
"publishDateTime": "2019-07-02T20:42:12.000Z",
|
|
86
86
|
"expireDateTime": null,
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import axios from 'axios'
|
|
2
|
+
|
|
3
|
+
function issueIsValid(issue) {
|
|
4
|
+
return !!issue.firstName && !!issue.lastName && !!issue.email && !!issue.issue
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export default async function sendAccessibilityIssue(issue, endpoint, apiKey, authCode) {
|
|
8
|
+
if (!issueIsValid(issue)) {
|
|
9
|
+
throw new Error('The issue object is incomplete or invalid.')
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const payload = {
|
|
13
|
+
name: `${issue.firstName} ${issue.lastName}`,
|
|
14
|
+
email: issue.email,
|
|
15
|
+
phone: issue.phone || '',
|
|
16
|
+
subject: 'Accessibility Issue Reported via External ASD20 Website',
|
|
17
|
+
html: `
|
|
18
|
+
<p><strong>Issue Details:</strong></p>
|
|
19
|
+
<p>${issue.issue}</p>
|
|
20
|
+
<p><strong>Mailing Address:</strong> ${issue.address || 'Not provided'}</p>
|
|
21
|
+
<p><strong>Organization:</strong> ${issue.organization || 'Not provided'}</p>
|
|
22
|
+
`,
|
|
23
|
+
category: Number(process.env.HAPPYFOX_CATEGORY_ID),
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
try {
|
|
27
|
+
const response = await axios.post(endpoint, payload, {
|
|
28
|
+
headers: {
|
|
29
|
+
Authorization: `Basic ${btoa(`${apiKey}:${authCode}`)}`,
|
|
30
|
+
'Content-Type': 'application/json',
|
|
31
|
+
Accept: 'application/json'
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
return response.data
|
|
36
|
+
} catch (error) {
|
|
37
|
+
if (error.response) {
|
|
38
|
+
throw new Error(
|
|
39
|
+
`HappyFox error ${error.response.status}: ${JSON.stringify(
|
|
40
|
+
error.response.data
|
|
41
|
+
)}`
|
|
42
|
+
)
|
|
43
|
+
} else {
|
|
44
|
+
throw new Error(`Request error: ${error.message}`)
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
File without changes
|