datatracker/client/agenda/AgendaQuickAccess.vue
Lars Eggert 9d5d9d5172
fix: replace deprecated bootstrap things (#5858)
* text-muted -> text-body-secondary

* navbar-dark is deprecated

* Remove FIXME block, not an issue anymore

* Remove `navbar-light`
2023-07-18 12:22:28 -05:00

312 lines
7.5 KiB
Vue

<template lang="pug">
.agenda-quickaccess
n-affix(:trigger-top='82')
.card.shadow-sm
.card-body
n-button(
id='agenda-quickaccess-filterbyareagroups-btn'
block
type='success'
size='large'
strong
@click='agendaStore.$patch({ filterShown: true })'
)
i.bi.bi-funnel.me-2
span {{ shortMode ? 'Filter...' : 'Filter Areas + Groups...' }}
n-badge.ms-2(:value='agendaStore.selectedCatSubs.length', processing)
n-button.mt-2(
v-if='!agendaStore.pickerMode'
id='agenda-quickaccess-picksessions-btn'
block
secondary
type='success'
size='large'
strong
@click='pickerStart'
)
i.bi.bi-ui-checks.me-2
span {{ shortMode ? 'Pick...' : 'Pick Sessions...' }}
.agenda-quickaccess-btnrow(v-else)
.agenda-quickaccess-btnrow-title {{ shortMode ? 'Sess. Pick' : 'Session Selection' }}
n-button.me-1(
v-if='!agendaStore.pickerModeView'
id='agenda-quickaccess-applypick-btn'
type='success'
size='large'
strong
@click='pickerApply'
)
i.bi.bi-check2-square.me-2
span Apply
n-button.me-1(
v-else
id='agenda-quickaccess-modifypick-btn'
color='#6f42c1'
size='large'
strong
@click='pickerModify'
)
i.bi.bi-pencil-square.me-2
span Modify
n-button.ms-1(
id='agenda-quickaccess-discardpick-btn'
secondary
color='#666'
size='large'
strong
@click='pickerDiscard'
)
i.bi.bi-x-square.me-2
span Discard
n-divider: small.text-body-secondary Calendar
n-button.mt-2(
id='agenda-quickaccess-calview-btn'
block
color='#6c757d'
size='large'
strong
@click='agendaStore.$patch({ calendarShown: true })'
)
i.bi.bi-calendar3.me-2
span {{ shortMode ? 'Cal View' : 'Calendar View' }}
n-dropdown(
:options='downloadIcsOptions'
size='large'
:show-arrow='true'
trigger='click'
)
n-button.mt-2(
id='agenda-quickaccess-addtocal-btn'
block
secondary
color='#6c757d'
size='large'
strong
)
i.bi.bi-calendar-check.me-2
span {{ shortMode ? '.ics' : 'Add to your calendar...' }}
template(v-if='agendaStore.meetingDays.length > 0')
n-divider: small.text-body-secondary Jump to...
ul.nav.nav-pills.flex-column.small.agenda-quickaccess-jumpto
li.nav-item(v-if='agendaStore.isMeetingLive')
a.nav-link(
href='#now'
@click='scrollToNow'
)
i.bi.bi-arrow-right-short.d-none.d-xxl-inline.me-2
span Now
li.nav-item(v-for='day of agendaStore.meetingDays')
a.nav-link(
:class='agendaStore.dayIntersectId === day.slug ? `active` : ``'
:href='`#slot-` + day.slug'
@click='scrollToDay(day.slug, $event)'
)
i.bi.bi-arrow-right-short.d-none.d-xxl-inline.me-2
span {{day.label}}
</template>
<script setup>
import { computed, h } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { DateTime } from 'luxon'
import {
NAffix,
NBadge,
NButton,
NDivider,
NDropdown,
useMessage
} from 'naive-ui'
import { useAgendaStore } from './store'
import { useSiteStore } from '../shared/store'
import { getUrl } from '../shared/urls'
// MESSAGE PROVIDER
const message = useMessage()
// STORES
const agendaStore = useAgendaStore()
const siteStore = useSiteStore()
// ROUTER
const router = useRouter()
const route = useRoute()
// Download Ics Options
const downloadIcsOptions = [
{
key: 'subscribe',
type: 'render',
render: () => h('a', {
class: 'agenda-quickaccess-callinks',
href: `webcal://${window.location.host}${icsLink.value}`
}, [
h('i', { class: 'bi bi-calendar-week text-blue' }),
h('span', 'Subscribe... (webcal)')
])
},
{
key: 'download',
type: 'render',
render: () => h('a', {
class: 'agenda-quickaccess-callinks',
href: icsLink.value
}, [
h('i', { class: 'bi bi-arrow-down-square' }),
h('span', 'Download... (.ics)')
])
}
]
// COMPUTED
const shortMode = computed(() => {
return siteStore.viewport <= 1350
})
const icsLink = computed(() => {
if (agendaStore.pickerMode) {
const sessionKeywords = agendaStore.scheduleAdjusted.map(s => s.sessionKeyword)
return `${getUrl('meetingCalIcs', { meetingNumber: agendaStore.meeting.number })}?show=${sessionKeywords.join(',')}`
} else if (agendaStore.selectedCatSubs.length > 0) {
return `${getUrl('meetingCalIcs', { meetingNumber: agendaStore.meeting.number })}?show=${agendaStore.selectedCatSubs.join(',')}`
} else {
return `${getUrl('meetingCalIcs', { meetingNumber: agendaStore.meeting.number })}`
}
})
// METHODS
function pickerStart () {
agendaStore.$patch({ pickerMode: true })
}
function pickerApply () {
agendaStore.$patch({ pickerModeView: true })
agendaStore.persistMeetingPreferences()
}
function pickerModify () {
agendaStore.$patch({ pickerModeView: false })
}
function pickerDiscard () {
agendaStore.$patch({ pickerMode: false })
if (route.query.show) {
router.push({ query: null })
}
}
function scrollToDay (dayId, ev) {
ev.preventDefault()
document.getElementById(`agenda-day-${dayId}`)?.scrollIntoView(true)
}
function scrollToNow (ev) {
ev.preventDefault()
const lastEventId = agendaStore.findCurrentEventId()
if (lastEventId) {
document.getElementById(`agenda-rowid-${lastEventId}`)?.scrollIntoView(true)
} else {
message.warning('There is no event happening right now.')
}
}
</script>
<style lang="scss">
.agenda-quickaccess {
width: 300px;
@media screen and (max-width: 1350px) {
width: 150px !important;
}
.card {
width: 300px;
@media screen and (max-width: 1350px) {
width: 150px;
.card-body {
padding: .5rem;
}
}
}
.card-body .n-button {
overflow: hidden;
}
&-btnrow {
border: 1px solid #CCC;
padding: 8px 6px 6px 6px;
border-radius: 5px;
display: flex;
justify-content: stretch;
position: relative;
text-align: center;
margin-top: 12px;
@media screen and (max-width: 1350px) {
flex-direction: column;
}
&-title {
position: absolute;
top: -8px;
font-size: 9px;
font-weight: 600;
color: #999;
left: 50%;
padding: 0 5px;
background-color: #FFF;
transform: translate(-50%, 0);
text-transform: uppercase;
}
button {
flex: 1;
@media screen and (max-width: 1350px) {
padding: 12px 0;
margin-left: 0 !important;
margin-right: 0 !important;
& + button {
margin-top: 6px;
}
}
}
}
.n-divider {
margin-top: 15px;
margin-bottom: 15px;
}
&-callinks {
padding: 8px 16px;
display: flex;
text-decoration: none;
align-items: center;
&:hover, &:focus {
text-decoration: underline;
}
> i {
font-size: var(--n-font-size);
}
> span {
margin-left: 12px;
}
}
}
</style>