Skip to content

Commit c4b9cb2

Browse files
chore: merge main into feat/tzaware
2 parents a124eb8 + 0caf946 commit c4b9cb2

19 files changed

Lines changed: 164 additions & 51 deletions

client/App.vue

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ n-theme
44
.app-error(v-if='siteStore.criticalError')
55
i.bi.bi-x-octagon-fill.me-2
66
span {{siteStore.criticalError}}
7+
.app-error-link(v-if='siteStore.criticalError && siteStore.criticalErrorLink')
8+
a(:href='siteStore.criticalErrorLink') {{siteStore.criticalErrorLinkText}} #[i.bi.bi-arrow-right-square-fill.ms-2]
79
.app-container(ref='appContainer')
810
router-view.meeting
911
</template>
@@ -56,4 +58,23 @@ onBeforeUnmount(() => {
5658
padding: 1rem;
5759
text-align: center;
5860
}
61+
62+
.app-error-link {
63+
background-color: lighten($red-100, 5%);
64+
border-radius: 0 0 5px 5px;
65+
color: #FFF;
66+
font-weight: 500;
67+
font-size: .9em;
68+
padding: .7rem 1rem;
69+
text-align: center;
70+
71+
a {
72+
color: $red-700;
73+
text-decoration: none;
74+
75+
&:hover, &:focus {
76+
text-decoration: underline;
77+
}
78+
}
79+
}
5980
</style>

client/agenda/AgendaDetailsModal.vue

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ import {
152152
} from 'naive-ui'
153153
154154
import { useAgendaStore } from './store'
155+
import { getUrl } from '../shared/urls'
155156
156157
// PROPS
157158
@@ -205,10 +206,22 @@ const eventDetails = computed(() => {
205206
title: props.event.type === 'regular' ? `${props.event.groupName} (${props.event.acronym})` : props.event.name,
206207
showAgenda: props.event.flags.showAgenda,
207208
materialsUrl: materialsUrl,
208-
detailsUrl: `/meeting/${agendaStore.meeting.number}/session/${props.event.acronym}/`,
209-
tarUrl: `/meeting/${agendaStore.meeting.number}/agenda/${props.event.acronym}-drafts.tgz`,
210-
pdfUrl: `/meeting/${agendaStore.meeting.number}/agenda/${props.event.acronym}-drafts.pdf`,
211-
notepadUrl: `https://notes.ietf.org/notes-ietf-${agendaStore.meeting.number}-${props.event.type === 'plenary' ? 'plenary' : props.event.acronym}`,
209+
detailsUrl: getUrl('meetingDetails', {
210+
meetingNumber: agendaStore.meeting.number,
211+
eventAcronym: props.event.acronym
212+
}),
213+
tarUrl: getUrl('meetingMaterialsTar', {
214+
meetingNumber: agendaStore.meeting.number,
215+
eventAcronym: props.event.acronym
216+
}),
217+
pdfUrl: getUrl('meetingMaterialsPdf', {
218+
meetingNumber: agendaStore.meeting.number,
219+
eventAcronym: props.event.acronym
220+
}),
221+
notepadUrl: getUrl('meetingNotes', {
222+
meetingNumber: agendaStore.meeting.number,
223+
eventAcronym: props.event.type === 'plenary' ? 'plenary' : props.event.acronym
224+
})
212225
}
213226
})
214227

client/agenda/AgendaFilter.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ n-drawer(v-model:show='state.isShown', placement='bottom', :height='state.drawer
6060
)
6161
template(#trigger)
6262
span.badge BoF
63-
span #[a(href='https://www.ietf.org/how/bofs/', target='_blank') Birds of a Feather] sessions (BoFs) are initial discussions about a particular topic of interest to the IETF community.
63+
span #[a(:href='getUrl(`bofDefinition`)', target='_blank') Birds of a Feather] sessions (BoFs) are initial discussions about a particular topic of interest to the IETF community.
6464
</template>
6565

6666
<script setup>
@@ -77,6 +77,7 @@ import {
7777
} from 'naive-ui'
7878
7979
import { useAgendaStore } from './store'
80+
import { getUrl } from '../shared/urls'
8081
8182
// STORES
8283

client/agenda/AgendaMobileBar.vue

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import {
3232
3333
import { useAgendaStore } from './store'
3434
import { useSiteStore } from '../shared/store';
35+
import { getUrl } from '../shared/urls'
3536
3637
// MESSAGE PROVIDER
3738
@@ -64,11 +65,11 @@ function downloadIcs (key) {
6465
let icsUrl = ''
6566
if (agendaStore.pickerMode) {
6667
const sessionKeywords = agendaStore.scheduleAdjusted.map(s => s.sessionKeyword)
67-
icsUrl = `/meeting/${agendaStore.meeting.number}/agenda.ics?show=${sessionKeywords.join(',')}`
68+
icsUrl = `${getUrl('meetingCalIcs', { meetingNumber: agendaStore.meeting.number })}?show=${sessionKeywords.join(',')}`
6869
} else if (agendaStore.selectedCatSubs.length > 0) {
69-
icsUrl = `/meeting/${agendaStore.meeting.number}/agenda.ics?show=${agendaStore.selectedCatSubs.join(',')}`
70+
icsUrl = `${getUrl('meetingCalIcs', { meetingNumber: agendaStore.meeting.number })}?show=${agendaStore.selectedCatSubs.join(',')}`
7071
} else {
71-
icsUrl = `/meeting/${agendaStore.meeting.number}/agenda.ics`
72+
icsUrl = `${getUrl('meetingCalIcs', { meetingNumber: agendaStore.meeting.number })}`
7273
}
7374
if (key === 'subscribe') {
7475
window.location.assign(`webcal://${window.location.host}${icsUrl}`)

client/agenda/AgendaQuickAccess.vue

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,8 @@ import {
120120
} from 'naive-ui'
121121
122122
import { useAgendaStore } from './store'
123-
import { useSiteStore } from '../shared/store';
123+
import { useSiteStore } from '../shared/store'
124+
import { getUrl } from '../shared/urls'
124125
125126
// MESSAGE PROVIDER
126127
@@ -181,11 +182,11 @@ function downloadIcs (key) {
181182
let icsUrl = ''
182183
if (agendaStore.pickerMode) {
183184
const sessionKeywords = agendaStore.scheduleAdjusted.map(s => s.sessionKeyword)
184-
icsUrl = `/meeting/${agendaStore.meeting.number}/agenda.ics?show=${sessionKeywords.join(',')}`
185+
icsUrl = `${getUrl('meetingCalIcs', { meetingNumber: agendaStore.meeting.number })}?show=${sessionKeywords.join(',')}`
185186
} else if (agendaStore.selectedCatSubs.length > 0) {
186-
icsUrl = `/meeting/${agendaStore.meeting.number}/agenda.ics?show=${agendaStore.selectedCatSubs.join(',')}`
187+
icsUrl = `${getUrl('meetingCalIcs', { meetingNumber: agendaStore.meeting.number })}?show=${agendaStore.selectedCatSubs.join(',')}`
187188
} else {
188-
icsUrl = `/meeting/${agendaStore.meeting.number}/agenda.ics`
189+
icsUrl = `${getUrl('meetingCalIcs', { meetingNumber: agendaStore.meeting.number })}`
189190
}
190191
if (key === 'subscribe') {
191192
window.location.assign(`webcal://${window.location.host}${icsUrl}`)

client/agenda/AgendaScheduleList.vue

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ import AgendaDetailsModal from './AgendaDetailsModal.vue'
202202
203203
import { useAgendaStore } from './store'
204204
import { useSiteStore } from '../shared/store'
205+
import { getUrl } from '../shared/urls'
205206
206207
// MESSAGE PROVIDER
207208
@@ -275,14 +276,20 @@ const meetingEvents = computed(() => {
275276
id: `lnk-${item.id}-tar`,
276277
label: 'Download meeting materials as .tar archive',
277278
icon: 'file-zip',
278-
href: `/meeting/${agendaStore.meeting.number}/agenda/${item.acronym}-drafts.tgz`,
279+
href: getUrl('meetingMaterialsTar', {
280+
meetingNumber: agendaStore.meeting.number,
281+
eventAcronym: item.acronym
282+
}),
279283
color: 'brown'
280284
})
281285
links.push({
282286
id: `lnk-${item.id}-pdf`,
283287
label: 'Download meeting materials as PDF file',
284288
icon: 'file-pdf',
285-
href: `/meeting/${agendaStore.meeting.number}/agenda/${item.acronym}-drafts.pdf`,
289+
href: getUrl('meetingMaterialsPdf', {
290+
meetingNumber: agendaStore.meeting.number,
291+
eventAcronym: item.acronym
292+
}),
286293
color: 'red'
287294
})
288295
}
@@ -291,7 +298,10 @@ const meetingEvents = computed(() => {
291298
id: `lnk-${item.id}-note`,
292299
label: 'Notepad for note-takers',
293300
icon: 'journal-text',
294-
href: `https://notes.ietf.org/notes-ietf-${agendaStore.meeting.number}-${item.type === 'plenary' ? 'plenary' : item.acronym}`,
301+
href: getUrl('meetingNotes', {
302+
meetingNumber: agendaStore.meeting.number,
303+
eventAcronym: item.type === 'plenary' ? 'plenary' : item.acronym
304+
}),
295305
color: 'blue'
296306
})
297307
}
@@ -404,7 +414,10 @@ const meetingEvents = computed(() => {
404414
id: `lnk-${item.id}-rec`,
405415
label: 'Session recording',
406416
icon: 'film',
407-
href: `https://www.meetecho.com/ietf${agendaStore.meeting.number}/recordings#${item.acronym.toUpperCase()}`,
417+
href: getUrl('meetingMeetechoRecordings', {
418+
meetingNumber: agendaStore.meeting.number,
419+
eventAcronym: item.acronym.toUpperCase()
420+
}),
408421
color: 'purple'
409422
})
410423
}

client/agenda/store.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,9 @@ export const useAgendaStore = defineStore('agenda', {
183183
console.error(err)
184184
const siteStore = useSiteStore()
185185
siteStore.$patch({
186-
criticalError: `Failed to load this meeting: ${err.message}`
186+
criticalError: `Failed to load this meeting: ${err.message}`,
187+
criticalErrorLink: meetingNumber ? `/meeting/${meetingNumber}/agenda.txt` : `/meeting/agenda.txt`,
188+
criticalErrorLinkText: 'Switch to text-only agenda version'
187189
})
188190
}
189191

client/shared/store.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import { defineStore } from 'pinia'
33
export const useSiteStore = defineStore('site', {
44
state: () => ({
55
criticalError: null,
6+
criticalErrorLink: null,
7+
criticalErrorLinkText: null,
68
isMobile: /Mobi/i.test(navigator.userAgent),
79
viewport: Math.round(window.innerWidth)
810
})

client/shared/urls.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import template from 'lodash-es/template'
2+
import transform from 'lodash-es/transform'
3+
4+
const urls = {
5+
bofDefinition: 'https://www.ietf.org/how/bofs/',
6+
meetingCalIcs: '/meeting/{meetingNumber}/agenda.ics',
7+
meetingDetails: '/meeting/{meetingNumber}/session/{eventAcronym}/',
8+
meetingMaterialsPdf: '/meeting/{meetingNumber}/agenda/{eventAcronym}-drafts.pdf',
9+
meetingMaterialsTar: '/meeting/{meetingNumber}/agenda/{eventAcronym}-drafts.tgz',
10+
meetingMeetechoRecordings: 'https://www.meetecho.com/ietf{meetingNumber}/recordings#{eventAcronym}',
11+
meetingNotes: 'https://notes.ietf.org/notes-ietf-{meetingNumber}-{eventAcronym}'
12+
}
13+
14+
const interpolate = /{([\s\S]+?)}/g
15+
const compiled = transform(urls, (result, value, key) => {
16+
result[key] = template(value, { interpolate })
17+
}, {})
18+
19+
/**
20+
* Get an URL and replace tokens with provided values.
21+
*
22+
* @param {string} key The key of the URL template to use.
23+
* @param {Object} [tokens] An object of tokens to replace in the URL template.
24+
* @returns {string} URL with tokens replaced with the provided values.
25+
*/
26+
export const getUrl = (key, tokens = {}) => {
27+
if (!key) { throw new Error('Must provide a key for getUrl()') }
28+
if (!compiled[key]) { throw new Error('Invalid getUrl() key') }
29+
return compiled[key](tokens)
30+
}

ietf/dbtemplate/templates/dbtemplate/template_list.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ <h1>Defined templates for group {{ group }}</h1>
66
{% if template_list %}
77
<ul>
88
{% for template in template_list %}
9-
<li><a href="{% url "ietf.dbtemplate.views.template_edit" group.acronym template.id %}">{{ template }}</a></li>
9+
<li><a href="{% url "ietf.dbtemplate.views.group_template_edit" group.acronym template.id %}">{{ template }}</a></li>
1010
{% endfor %}
1111
</ul>
1212
{% else %}

0 commit comments

Comments
 (0)