Skip to content

Commit

Permalink
Merge branch 'main' into APPS-3078_add-highlighted-state
Browse files Browse the repository at this point in the history
  • Loading branch information
farosFreed authored Dec 12, 2024
2 parents 295f646 + 90fdeab commit c045145
Show file tree
Hide file tree
Showing 19 changed files with 1,075 additions and 158 deletions.
28 changes: 28 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,31 @@
# [3.41.0](https://github.com/UCLALibrary/ucla-library-website-components/compare/v3.40.0...v3.41.0) (2024-12-11)


### Features

* APPS-3100 Decouple SectionRemoveSearchFilter ([#666](https://github.com/UCLALibrary/ucla-library-website-components/issues/666)) ([28ddd0b](https://github.com/UCLALibrary/ucla-library-website-components/commit/28ddd0bb960a5840754debd05012c7925b33a830))

# [3.40.0](https://github.com/UCLALibrary/ucla-library-website-components/compare/v3.39.2...v3.40.0) (2024-12-10)


### Features

* APPS 3079 Calendar Component EventCard Popup ([#661](https://github.com/UCLALibrary/ucla-library-website-components/issues/661)) ([dc24f85](https://github.com/UCLALibrary/ucla-library-website-components/commit/dc24f852c908c7c68a3bf8e43e73fb0457b07283))

## [3.39.2](https://github.com/UCLALibrary/ucla-library-website-components/compare/v3.39.1...v3.39.2) (2024-12-07)


### Bug Fixes

* APPS-3090 Move CSS from EventSeries page to SectionStaffArticleList component for FTVA Theme ([#663](https://github.com/UCLALibrary/ucla-library-website-components/issues/663)) ([10aaab7](https://github.com/UCLALibrary/ucla-library-website-components/commit/10aaab75601130822245c89cbfb7c9225597838a))

## [3.39.1](https://github.com/UCLALibrary/ucla-library-website-components/compare/v3.39.0...v3.39.1) (2024-12-06)


### Bug Fixes

* APPS-3073 Datefilter bugs & enhancements ([#660](https://github.com/UCLALibrary/ucla-library-website-components/issues/660)) ([64b7825](https://github.com/UCLALibrary/ucla-library-website-components/commit/64b7825f7818175067f988d3562fb84dff2c37aa))

# [3.39.0](https://github.com/UCLALibrary/ucla-library-website-components/compare/v3.38.0...v3.39.0) (2024-12-03)


Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "ucla-library-website-components",
"type": "module",
"private": false,
"version": "3.39.0",
"version": "3.41.0",
"main": "./dist/ucla-library-website-components.umd.cjs",
"module": "./dist/ucla-library-website-components.js",
"style": "./dist/style.css",
Expand Down
185 changes: 155 additions & 30 deletions src/lib-components/BaseCalendar.vue
Original file line number Diff line number Diff line change
@@ -1,63 +1,145 @@
<script setup>
import { computed, onMounted, useTemplateRef } from 'vue'
<script setup lang="ts">
import { computed, onMounted, onUnmounted, ref, useTemplateRef } from 'vue'
import type { PropType, Ref } from 'vue'
import format from 'date-fns/format'
import BlockCardWithImage from './BlockCardWithImage.vue'
import BlockEventDetail from './BlockEventDetail.vue'
import BlockTag from './BlockTag.vue'
import { useTheme } from '@/composables/useTheme'
import type { MediaItemType } from '@/types/types'
interface Event {
id: string
startDateWithTime: string
title: string
to: string
location?: { title: string; publicUrl?: string }[]
}
interface TagLabels {
title?: string
isHighlighted?: boolean
}
interface CalendarEvent extends Event {
ftvaEventScreeningDetails: { tagLabels: TagLabels[] }[]
imageCarousel: { image: MediaItemType[] }[]
}
interface SelectedCalendarEvent extends Event {
start: Date
end: Date
time: string
tagLabels?: TagLabels[]
image: MediaItemType
}
const { defaultEventCalendar, events, firstEventMonth } = defineProps({
defaultEventCalendar: {
type: Boolean,
default: true
// True: Default calendar with fixed components
// False: Minimal calendar or with custom components
},
const { events, value } = defineProps({
events: {
type: Array,
type: Array as PropType<CalendarEvent[]>,
default: () => [],
},
value: {
firstEventMonth: {
type: Array,
default: () => [new Date()]
// Sets calendar to month of earliest event
// Default: Calendar opens to month of current date
}
})
// const newDateRef = ref(value)
const calendarRef = useTemplateRef<HTMLDivElement>('calendar')
const firstEventMonthRef = ref(firstEventMonth)
const calendarRef = useTemplateRef('calendar')
// Vuetify Popup/Dialog
const eventItemRef: Ref<CalendarEvent | any> = ref({})
const selectedEventObj: Ref<SelectedCalendarEvent | any> = ref({})
const selectedEventElement = ref<HTMLElement | null>(null)
onMounted(() => {
updateCalendarWeekdays()
updateCalendarHeaderElements()
window.addEventListener('click', handleSelectedEventItemDeselect)
})
// Vuetify calendar day format is single-lettered: S, M, etc.
// Update day to full name: Sunday, Monday, etc.
// Default header button text is 'Today'; update to 'This Month'
function updateCalendarHeaderElements() {
const weekDayLabels = calendarRef.value?.querySelectorAll('.v-calendar-weekly__head-weekday-with-weeknumber')
const todayBtnElem = calendarRef.value?.querySelector('.v-calendar-header__today .v-btn__content') as HTMLElement
const weekDays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']
weekDayLabels?.forEach((elem, idx) => (elem as HTMLElement).innerText = weekDays[idx])
todayBtnElem.innerText = 'This Month'
}
// Remove selected style of previous selected event
function handleSelectedEventItemDeselect() {
if (selectedEventElement.value)
selectedEventElement.value.classList.remove('selected-event')
}
const parsedEvents = computed(() => {
if (events.length === 0)
return []
const calendarEvents = events.map((obj) => {
const calendarEvents = events.map((obj: CalendarEvent) => {
const rawDate = obj.startDateWithTime
return {
// Required object keys for Vuetify calendar
title: obj.title,
start: new Date(rawDate),
end: new Date(rawDate),
time: formatEventTime(rawDate),
// All other event data
id: obj.id,
startDateWithTime: obj.startDateWithTime,
tagLabels: obj.ftvaEventScreeningDetails[0]?.tagLabels,
image: obj.imageCarousel[0]?.image[0],
location: obj.location,
to: obj.to
}
})
return calendarEvents
})
// console.log(parsedEvents.value)
// Format time as '00:00 PM'
function formatEventTime(date) {
function formatEventTime(date: string) {
const formattedTime = format(new Date(date), 'h:mm aaa')
return formattedTime.toUpperCase()
}
// Vuetify calendar day format is single-lettered: S, M, etc.
// Update day to full name: Sunday, Monday, etc.
function updateCalendarWeekdays() {
const weekDayLabels = calendarRef.value.querySelectorAll('.v-calendar-weekly__head-weekday-with-weeknumber')
function showEventItemPopup(calendarEventObj: SelectedCalendarEvent | Record <string, unknown>) {
// Remove selected style of previous selected event
handleSelectedEventItemDeselect()
const weekDays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']
selectedEventObj.value = calendarEventObj
const selectedElem = eventItemRef.value[`item-${calendarEventObj.id}`]
// Set event as new selected event
selectedEventElement.value = selectedElem
weekDayLabels.forEach((elem, idx) => elem.innerHTML = weekDays[idx])
selectedEventElement.value?.classList.add('selected-event')
}
onUnmounted(() => {
window.removeEventListener('click', handleSelectedEventItemDeselect)
})
const theme = useTheme()
const classes = computed(() => {
Expand All @@ -73,26 +155,69 @@ const classes = computed(() => {
<div class="calendar-wrapper">
<v-sheet class="calendar-body">
<v-calendar
v-model="firstEventMonthRef"
:events="parsedEvents"
view-mode="month"
>
<!-- Vuetify calendar header slot -->
<!--
<template #header="header">
{{ header.title }}
</template>
-->
<!-- Vuetify calendar event slot -->
<!-- Slot prop holds each parsedEvent object -->
<template #event="event">
<div class="calendar-event-item">
<p class="calendar-event-title">
<button :ref="(el) => { eventItemRef[`item-${event.event.id}`] = el }" class="calendar-event-item" @click="showEventItemPopup(event.event)">
<span class="calendar-event-title">
{{ event.event.title }}
</p>
<p class="calendar-event-time">
</span>
<span class="calendar-event-time">
{{ event.event.time }}
</p>
</div>
</span>

<!-- Event item popup -->
<v-menu
activator="parent"
:open-on-click="true"
:close-on-content-click="false"
location="start bottom"
origin="auto"
offset="10"
opacity="0"
>
<v-card width="320" style="overflow: initial; z-index: initial" :hover="false" :link="true" :to="selectedEventObj.to">
<!-- Default Event Calendar -->
<div v-if="defaultEventCalendar" class="calendar-event-popup-wrapper">
<BlockCardWithImage
:image="selectedEventObj.image"
:title="selectedEventObj.title"
/>
<div class="block-tag-wrapper">
<BlockTag
v-for="tag in selectedEventObj.tagLabels"
:key="`tag-${tag.title}`"
:label="tag.title"
:is-secondary="true"
:is-highlighted="tag.isHighlighted ? tag.isHighlighted : false"
:class="{ highlighted: tag.isHighlighted }"
/>
</div>
<BlockEventDetail
:start-date="selectedEventObj.startDateWithTime"
:time="selectedEventObj.startDateWithTime"
:locations="selectedEventObj.location"
/>
</div>

<!-- Slot for new components -->
<div v-else-if="$slots.calendarSlotComponent" class="calendar-slot-wrapper">
<slot name="calendarSlotComponent" :event="selectedEventObj" />
</div>

<!-- Default Vuetify component -->
<v-list v-else>
<v-list-item
:title="selectedEventObj.title"
/>
</v-list>
</v-card>
</v-menu>
</button>
</template>
</v-calendar>
</v-sheet>
Expand Down
23 changes: 16 additions & 7 deletions src/lib-components/BlockRemoveSearchFilter.vue
Original file line number Diff line number Diff line change
Expand Up @@ -65,19 +65,28 @@ function closeBlockFilter() {
</script>
<template>
<button type="button" :class="classes" @click="closeBlockFilter">
<BlockTag :label="title" :icon-name="iconName" :theme="theme" :is-secondary="true">
<span class="button-close" :class="{ 'button-selected': isSelected && theme === 'ftva' }">
<button
type="button"
:class="classes"
@click="closeBlockFilter"
>
<BlockTag
:label="title"
:icon-name="iconName"
:theme="theme"
:is-secondary="true"
>
<span
class="button-close"
:class="{ 'button-selected': isSelected && theme === 'ftva' }"
>
<component :is="removeIcons[removeIcon]" />
</span>
</BlockTag>
</button>
</template>
<style
lang="scss"
scoped
>
<style lang="scss" scoped>
@import "@/styles/default/_block-remove-search-filter.scss";
@import "@/styles/ftva/_block-remove-search-filter.scss";
</style>
2 changes: 1 addition & 1 deletion src/lib-components/CardMeta.vue
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ const classes = computed(() => {
<template>
<div :class="classes">
<div class="linked-category">
<div v-if="$slots.linkedcategoryslot" class="linked-category">
<slot name="linkedcategoryslot" />
</div>
Expand Down
Loading

0 comments on commit c045145

Please sign in to comment.