Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updater and website fixes #108

Merged
merged 4 commits into from
Sep 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 20 additions & 15 deletions API/gimvicurnik/updaters/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,15 +163,22 @@ def handle_document(self, document: DocumentInfo, span: Span) -> None:
span.set_tag("document.modified", document.modified)
span.set_tag("document.action", "crashed")

# == DOCUMENT EFFECTIVE

# Get the document's effective date using the subclassed method
# This may return none for documents without an effective date
# If this fails, we can't do anything other than to skip the document
effective = self.get_document_effective(document)

# == DOCUMENT RECORD (GET)

# Try to find an existing document record
record = self.retrieve_document(document)
record = self.retrieve_document(document, effective)

# == DOCUMENT PROCESSING

# Get the modified time if it is set, otherwise use the current time
created = document.created or datetime.datetime.utcnow()
created = document.created or datetime.datetime.now(datetime.timezone.utc)
modified = document.modified or created

# Check if the document has changed without downloading it and comparing hashes
Expand All @@ -193,8 +200,8 @@ def handle_document(self, document: DocumentInfo, span: Span) -> None:
# If this fails, we can't do anything other than to skip the document
stream, new_hash = self.download_document(document)

# Check if the document hash has changed
if record and record.parsed and record.hash == new_hash:
# Check if the document hash or document URL have changed
if record and record.parsed and record.hash == new_hash and record.url == document.url:
changed = False
else:
action = "updated"
Expand Down Expand Up @@ -233,11 +240,6 @@ def handle_document(self, document: DocumentInfo, span: Span) -> None:

return

# Get the document's effective date using the subclassed method
# This may return none for documents without an effective date
# If this fails, we can't do anything other than to skip the document
effective = self.get_document_effective(document)

if parsable:
# If there is no date, we can't do anything other than to skip the document
if not effective:
Expand Down Expand Up @@ -320,14 +322,17 @@ def handle_document(self, document: DocumentInfo, span: Span) -> None:
self.logger.info("Skipped because the %s document for %s is already stored", document.type.value, effective)
# fmt: on

def retrieve_document(self, document: DocumentInfo) -> Document | None:
def retrieve_document(self, document: DocumentInfo, effective: datetime.date | None) -> Document | None:
"""Get a document record from the database. May be set by subclasses."""

return (
self.session.query(Document)
.filter(Document.type == document.type, Document.url == document.url)
.first()
)
# Normally, the document URL should match
criterion = Document.url == document.url

if effective:
# If effective date is set, it may also match instead of the URL
criterion |= Document.effective == effective

return self.session.query(Document).filter(Document.type == document.type, criterion).first()

@with_span(op="download")
def download_document(self, document: DocumentInfo) -> tuple[BytesIO, str]:
Expand Down
2 changes: 1 addition & 1 deletion API/gimvicurnik/updaters/menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ def get_document_effective(self, document: DocumentInfo) -> datetime.date:
# jedilnik-kosilo-YYYY-MM-DD(-popravek).pdf
# jedilnik-malica-YYYY-MM-DD(-popravek).pdf
date = re.search(
r"jedilnik-(?:kosilo|malica)-(\d+)-(\d+)-(\d+)(?:-[\w-]*)?\.(?:pdf|xlsx)", document.url
r"jedilnik-(?:kosilo|malica|K|M)-(\d+)-(\d+)-(\d+)(?:-[\w-]*)?\.(?:pdf|xlsx)", document.url
)

# The specified date is commonly Monday of the effective week
Expand Down
4 changes: 2 additions & 2 deletions API/gimvicurnik/updaters/timetable.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import re
import typing
from collections import defaultdict
from datetime import datetime
from datetime import datetime, timezone
from hashlib import sha256

import requests
Expand Down Expand Up @@ -167,7 +167,7 @@ def _parse(self, document: Document | None, raw_data: str, new_hash: str, span:
created = False

document.type = DocumentType.TIMETABLE
document.modified = datetime.utcnow()
document.modified = datetime.now(timezone.utc)
document.url = self.config.url
document.hash = new_hash
self.session.add(document)
Expand Down
19 changes: 13 additions & 6 deletions website/src/components/TimetableDisplay.vue
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
<script setup lang="ts">
import { useIntervalFn } from '@vueuse/core'
import { storeToRefs } from 'pinia'
import { computed } from 'vue'
import { computed, ref } from 'vue'

import TimetableEmptyClassrooms from '@/components/TimetableEmptyClassrooms.vue'
import TimetableLesson from '@/components/TimetableLesson.vue'
import { useSessionStore } from '@/stores/session'
import { EntityType, useSettingsStore } from '@/stores/settings'
import { type MergedLesson, useTimetableStore } from '@/stores/timetable'
import { getCurrentDay } from '@/utils/days'
import { getCurrentDay, getIsWeekend } from '@/utils/days'
import { localizedWeekdays } from '@/utils/localization'
import { getCurrentTime, lessonTimes } from '@/utils/times'

Expand All @@ -25,9 +26,15 @@ const { lessons } = storeToRefs(useTimetableStore())
const { showHoursInTimetable, highlightCurrentTime, enableLessonDetails } =
storeToRefs(useSettingsStore())

const isWeekend = [0, 6].includes(new Date().getDay())
const currentDay = getCurrentDay()
const currentTime = getCurrentTime()
const isWeekend = ref(getIsWeekend())
const currentDay = ref(getCurrentDay())
const currentTime = ref(getCurrentTime())

useIntervalFn(() => {
isWeekend.value = getIsWeekend()
currentDay.value = getCurrentDay()
currentTime.value = getCurrentTime()
}, 30000)

/**
* Determines the range of lesson times that need to be displayed in the timetable.
Expand All @@ -48,7 +55,7 @@ function lessonStyles(dayIndex: number, timeIndex: number) {
// prettier-ignore
return {
'bg-surface-highlighted': lessons.value[timeIndex][dayIndex]?.find(lesson => lesson.isSubstitution),
'current-time': highlightCurrentTime.value && !isWeekend && dayIndex === currentDay && timeIndex === currentTime,
'current-time': highlightCurrentTime.value && !isWeekend.value && dayIndex === currentDay.value && timeIndex === currentTime.value,
}
}

Expand Down
11 changes: 11 additions & 0 deletions website/src/utils/days.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ export function getCurrentDay(): number {
return currentDay - 1
}

/**
* Returns whether it is currently a weekend.
*/
export function getIsWeekend(): boolean {
return [0, 6].includes(new Date().getDay())
}

/**
* Returns the weekdays of the week of the given date.
*
Expand Down Expand Up @@ -54,5 +61,9 @@ export function getWeekdays(date: Date): Date[] {
* Returns the ISO date string of the given date.
*/
export function getISODate(date: Date): string {
// Make sure the date is UTC midnight, otherwise, conversion to ISO may be wrong
date = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()))

// Convert the date into ISO format and return the date part
return date.toISOString().split('T')[0]
}