Skip to content

Commit

Permalink
ci: merge main to release (#7871)
Browse files Browse the repository at this point in the history
ci: merge main to release
  • Loading branch information
rjsparks authored Aug 28, 2024
2 parents 2bf7374 + c458c09 commit 4635e3d
Show file tree
Hide file tree
Showing 24 changed files with 297 additions and 98 deletions.
2 changes: 1 addition & 1 deletion client/agenda/Agenda.vue
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@ function reconnectScrollObservers () {
scrollObserver.disconnect()
visibleDays.length = 0
for (const mDay of agendaStore.meetingDays) {
const el = document.getElementById(`agenda-day-${mDay.slug}`)
const el = document.getElementById(mDay.slug)
el.dataset.dayId = mDay.slug.toString()
el.dataset.dayTs = mDay.ts
scrollObserver.observe(el)
Expand Down
54 changes: 47 additions & 7 deletions client/agenda/AgendaMobileBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@

<script setup>
import { computed, h } from 'vue'
import {
NBadge,
NDropdown,
Expand All @@ -51,21 +50,48 @@ const siteStore = useSiteStore()
// Meeting Days
function optionToLink(opts){
const { key, label, icon } = opts
return {
...opts,
type: 'render',
render: () => h(
'a',
{
class: 'dropdown-link',
'data-testid': 'mobile-link',
href: `#${key}`
},
[
h(
'span',
icon()
),
h(
'span',
label
)
]
)
}
}
const jumpToDayOptions = computed(() => {
const days = []
if (agendaStore.isMeetingLive) {
days.push({
days.push(optionToLink({
label: 'Jump to Now',
key: 'now',
icon: () => h('i', { class: 'bi bi-arrow-down-right-square text-red' })
})
}))
}
for (const day of agendaStore.meetingDays) {
days.push({
days.push(optionToLink({
label: `Jump to ${day.label}`,
key: day.slug,
icon: () => h('i', { class: 'bi bi-arrow-down-right-square' })
})
}))
}
return days
})
Expand All @@ -90,14 +116,13 @@ const downloadIcsOptions = [
function jumpToDay (dayId) {
if (dayId === 'now') {
const lastEventId = agendaStore.findCurrentEventId()
if (lastEventId) {
document.getElementById(`agenda-rowid-${lastEventId}`)?.scrollIntoView(true)
} else {
message.warning('There is no event happening right now.')
}
} else {
document.getElementById(`agenda-day-${dayId}`)?.scrollIntoView(true)
document.getElementById(dayId)?.scrollIntoView(true)
}
}
Expand Down Expand Up @@ -162,4 +187,19 @@ function downloadIcs (key) {
}
}
}
.dropdown-link {
display: flex;
text-decoration:none;
gap: 0.2rem 0.5rem;
padding: 0.5em;
color: var(--bs-body-color);
&:hover,
&:focus {
background-color: var(--bs-dark-bg-subtle);
text-decoration: underline;
}
}
</style>
10 changes: 3 additions & 7 deletions client/agenda/AgendaQuickAccess.vue
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@
li.nav-item(v-for='day of agendaStore.meetingDays')
a.nav-link(
:class='agendaStore.dayIntersectId === day.slug ? `active` : ``'
:href='`#slot-` + day.slug'
:href='`#${day.slug}`'
@click='scrollToDay(day.slug, $event)'
)
i.bi.bi-arrow-right-short.d-none.d-xxl-inline.me-2
Expand All @@ -109,7 +109,6 @@
<script setup>
import { computed, h } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { DateTime } from 'luxon'
import {
NAffix,
NBadge,
Expand Down Expand Up @@ -200,14 +199,11 @@ function pickerDiscard () {
}
}
function scrollToDay (dayId, ev) {
ev.preventDefault()
document.getElementById(`agenda-day-${dayId}`)?.scrollIntoView(true)
function scrollToDay (daySlug, ev) {
document.getElementById(daySlug)?.scrollIntoView(true)
}
function scrollToNow (ev) {
ev.preventDefault()
const lastEventId = agendaStore.findCurrentEventId()
if (lastEventId) {
Expand Down
29 changes: 27 additions & 2 deletions client/agenda/AgendaScheduleList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
)
//- ROW - DAY HEADING -----------------------
template(v-if='item.displayType === `day`')
td(:id='`agenda-day-` + item.id', :colspan='pickerModeActive ? 6 : 5') {{item.date}}
td(:id='item.slug', :colspan='pickerModeActive ? 6 : 5') {{item.date}}
//- ROW - SESSION HEADING -------------------
template(v-else-if='item.displayType === `session-head`')
td.agenda-table-cell-check(v-if='pickerModeActive') &nbsp;
Expand Down Expand Up @@ -200,7 +200,7 @@ import {
import AgendaDetailsModal from './AgendaDetailsModal.vue'
import { useAgendaStore } from './store'
import { useAgendaStore, daySlugPrefix, daySlug } from './store'
import { useSiteStore } from '../shared/store'
import { getUrl } from '../shared/urls'
Expand Down Expand Up @@ -248,6 +248,7 @@ const meetingEvents = computed(() => {
if (itemDate.toISODate() !== acc.lastDate) {
acc.result.push({
id: item.id,
slug: daySlug(item),
key: `day-${itemDate.toISODate()}`,
displayType: 'day',
date: itemDate.toLocaleString(DateTime.DATE_HUGE),
Expand Down Expand Up @@ -575,6 +576,30 @@ function recalculateRedLine () {
}
}
/**
* On page load when browser location hash contains '#now' or '#agenda-day-*' then scroll accordingly
*/
;(function scrollToHashInit() {
if (!window.location.hash) {
return
}
if (!(window.location.hash === "#now" || window.location.hash.startsWith(`#${daySlugPrefix}`))) {
return
}
const unsubscribe = agendaStore.$subscribe((_mutation, agendaStoreState) => {
if (agendaStoreState.schedule.length === 0) {
return
}
unsubscribe() // we only need to scroll once, so unsubscribe from future updates
if(window.location.hash === "#now") {
const lastEventId = agendaStore.findCurrentEventId()
document.getElementById(`agenda-rowid-${lastEventId}`)?.scrollIntoView(true)
} else if(window.location.hash.startsWith(`#${daySlugPrefix}`)) {
document.getElementById(window.location.hash.substring(1))?.scrollIntoView(true)
}
})
})()
// MOUNTED
onMounted(() => {
Expand Down
7 changes: 6 additions & 1 deletion client/agenda/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ export const useAgendaStore = defineStore('agenda', {
meetingDays () {
const siteStore = useSiteStore()
return uniqBy(this.scheduleAdjusted, 'adjustedStartDate').sort().map(s => ({
slug: s.id.toString(),
slug: daySlug(s),
ts: s.adjustedStartDate,
label: siteStore.viewport < 1350 ? DateTime.fromISO(s.adjustedStartDate).toFormat('ccc LLL d') : DateTime.fromISO(s.adjustedStartDate).toLocaleString(DateTime.DATE_HUGE)
}))
Expand Down Expand Up @@ -292,3 +292,8 @@ function findFirstConferenceUrl (txt) {
} catch (err) { }
return null
}

export const daySlugPrefix = 'agenda-day-'
export function daySlug(s) {
return `${daySlugPrefix}${s.adjustedStartDate}` // eg 'agenda-day-2024-08-13'
}
4 changes: 2 additions & 2 deletions client/embedded.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import piniaPersist from 'pinia-plugin-persist'
import Embedded from './Embedded.vue'
import { createPiniaSingleton } from './shared/create-pinia-singleton'

// Initialize store (Pinia)

const pinia = createPinia()
const pinia = createPiniaSingleton()
pinia.use(piniaPersist)

// Mount App
Expand Down
4 changes: 2 additions & 2 deletions client/main.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import piniaPersist from 'pinia-plugin-persist'
import App from './App.vue'
import router from './router'
import { createPiniaSingleton } from './shared/create-pinia-singleton'

const app = createApp(App, {})

// Initialize store (Pinia)

const pinia = createPinia()
const pinia = createPiniaSingleton()
pinia.use(piniaPersist)
app.use(pinia)

Expand Down
6 changes: 6 additions & 0 deletions client/shared/create-pinia-singleton.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { createPinia } from 'pinia'

export function createPiniaSingleton(){
window.pinia = window.pinia ?? createPinia()
return window.pinia
}
30 changes: 30 additions & 0 deletions ietf/doc/migrations/0023_bofreqspamstate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Copyright The IETF Trust 2024, All Rights Reserved

from django.db import migrations


def forward(apps, schema_editor):
State = apps.get_model("doc", "State")
State.objects.get_or_create(
type_id="bofreq",
slug="spam",
defaults={"name": "Spam", "desc": "The BOF request is spam", "order": 5},
)


def reverse(apps, schema_editor):
State = apps.get_model("doc", "State")
Document = apps.get_model("doc", "Document")
assert not Document.objects.filter(
states__type="bofreq", states__slug="spam"
).exists()
State.objects.filter(type_id="bofreq", slug="spam").delete()


class Migration(migrations.Migration):

dependencies = [
("doc", "0022_remove_dochistory_internal_comments_and_more"),
]

operations = [migrations.RunPython(forward, reverse)]
13 changes: 11 additions & 2 deletions ietf/doc/templatetags/ballot_icon.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,14 @@ def sort_key(t):
positions = list(ballot.active_balloter_positions().items())
positions.sort(key=sort_key)

request = context.get("request")
ballot_edit_return_point_param = f"ballot_edit_return_point={request.path}"

right_click_string = ''
if has_role(user, "Area Director"):
right_click_string = 'oncontextmenu="window.location.href=\'%s\';return false;"' % urlreverse('ietf.doc.views_ballot.edit_position', kwargs=dict(name=doc.name, ballot_id=ballot.pk))
right_click_string = 'oncontextmenu="window.location.href=\'{}?{}\';return false;"'.format(
urlreverse('ietf.doc.views_ballot.edit_position', kwargs=dict(name=doc.name, ballot_id=ballot.pk)),
ballot_edit_return_point_param)

my_blocking = False
for i, (balloter, pos) in enumerate(positions):
Expand All @@ -113,10 +118,14 @@ def sort_key(t):
typename = "RSAB"
else:
typename = "IESG"

modal_url = "{}?{}".format(
urlreverse("ietf.doc.views_doc.ballot_popup", kwargs=dict(name=doc.name, ballot_id=ballot.pk)),
ballot_edit_return_point_param)

res = ['<a %s href="%s" data-bs-toggle="modal" data-bs-target="#modal-%d" aria-label="%s positions" title="%s positions (click to show more)" class="ballot-icon"><table' % (
right_click_string,
urlreverse("ietf.doc.views_doc.ballot_popup", kwargs=dict(name=doc.name, ballot_id=ballot.pk)),
modal_url,
ballot.pk,
typename,
typename,)]
Expand Down
29 changes: 29 additions & 0 deletions ietf/doc/templatetags/document_type_badge.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Copyright The IETF Trust 2015-2020, All Rights Reserved
from django import template
from django.conf import settings
from django.template.loader import render_to_string
from ietf.utils.log import log

register = template.Library()


@register.simple_tag
def document_type_badge(doc, snapshot, submission, resurrected_by):
context = {"doc": doc, "snapshot": snapshot, "submission": submission, "resurrected_by": resurrected_by}
if doc.type_id == "rfc":
return render_to_string(
"doc/badge/doc-badge-rfc.html",
context,
)
elif doc.type_id == "draft":
return render_to_string(
"doc/badge/doc-badge-draft.html",
context,
)
else:
error_message = f"Unsupported document type {doc.type_id}."
if settings.SERVER_MODE != 'production':
raise ValueError(error_message)
else:
log(error_message)
return ""
23 changes: 11 additions & 12 deletions ietf/doc/tests_ballot.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,9 @@ def test_cannot_edit_position_as_pre_ad(self):
r = self.client.post(url, dict(position="discuss", discuss="Test discuss text"))
self.assertEqual(r.status_code, 403)

# N.B. This test needs to be rewritten to exercise all types of ballots (iesg, irsg, rsab)
# and test against the output of the mailtriggers instead of looking for hardcoded values
# in the To and CC results. See #7864
def test_send_ballot_comment(self):
ad = Person.objects.get(user__username="ad")
draft = WgDraftFactory(ad=ad,group__acronym='mars')
Expand Down Expand Up @@ -1455,18 +1458,14 @@ def test_document_ballot_content_without_send_email_values(self):

class ReturnToUrlTests(TestCase):
def test_invalid_return_to_url(self):
self.assertRaises(
Exception,
lambda: parse_ballot_edit_return_point('/doc/', 'draft-ietf-opsawg-ipfix-tcpo-v6eh', '998718'),
)
self.assertRaises(
Exception,
lambda: parse_ballot_edit_return_point('/a-route-that-does-not-exist/', 'draft-ietf-opsawg-ipfix-tcpo-v6eh', '998718'),
)
self.assertRaises(
Exception,
lambda: parse_ballot_edit_return_point('https://example.com/phishing', 'draft-ietf-opsawg-ipfix-tcpo-v6eh', '998718'),
)
with self.assertRaises(ValueError):
parse_ballot_edit_return_point('/', 'draft-ietf-opsawg-ipfix-tcpo-v6eh', '998718')

with self.assertRaises(ValueError):
parse_ballot_edit_return_point('/a-route-that-does-not-exist/', 'draft-ietf-opsawg-ipfix-tcpo-v6eh', '998718')

with self.assertRaises(ValueError):
parse_ballot_edit_return_point('https://example.com/phishing', 'draft-ietf-opsawg-ipfix-tcpo-v6eh', '998718')

def test_valid_default_return_to_url(self):
self.assertEqual(parse_ballot_edit_return_point(
Expand Down
Loading

0 comments on commit 4635e3d

Please sign in to comment.