Skip to content

Commit

Permalink
changes for hours listing on homepage
Browse files Browse the repository at this point in the history
  • Loading branch information
dougchestnut committed Aug 16, 2023
1 parent 73994d6 commit 5642ec5
Show file tree
Hide file tree
Showing 3 changed files with 149 additions and 70 deletions.
15 changes: 9 additions & 6 deletions packages/data-wrap/src/LibrariesData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,16 @@ export class LibrariesData extends DrupalSearchData {
.fetchHours(start, count)
.then((hours: any) => {
this.items.forEach((library) => {
// Libraries can get their own hours, but we are spoon-feeding them in this case so we can make one request for all
if (library.hoursId)
library.setHours(
hours.find(
(h: { id: string | undefined }) => parseInt(<string>h.id, 10) === parseInt(<string>library.hoursId, 10)
)
if (library.hoursId) {
const matchingHours = hours.find(
(h: { id: string | undefined }) => parseInt(<string>h.id, 10) === parseInt(<string>library.hoursId, 10)
);
if (matchingHours) {
library.setHours(matchingHours);
} else {
console.warn(`No matching hours found for library with hoursId: ${library.hoursId}`);
}
}
});
});
}
Expand Down
129 changes: 85 additions & 44 deletions packages/data-wrap/src/Library.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { GeneralSearchResult } from './GeneralSearchResult.js';
import { Hours } from './Hours.js';

const SITE_LINK_BASE = "https://www.library.virginia.edu";

export class Library extends GeneralSearchResult {
public uuid?: string;
public body?: string;
Expand All @@ -27,68 +29,108 @@ export class Library extends GeneralSearchResult {
public children?: Library[];
public closureOverride?: number;
public hours?: Hours;
public priorityPlacement?: number;

public setHours(h?: Hours) {
if (!h) {
throw new Error("Invalid Hours object provided.");
}
this.hours = h;
}

public getHoursCalIds() {
let ids: number[] = new Array();
if (this.hoursId) ids.push(parseInt(this.hoursId));
if (this.children)
let ids: number[] = [];
if (this.hoursId) {
const parsedId = parseInt(this.hoursId);
if (isNaN(parsedId)) {
throw new Error(`Invalid hoursId value: ${this.hoursId}`);
}
ids.push(parsedId);
}

if (this.children) {
this.children.forEach((c) => {
if (c.hoursId) ids.push(parseInt(c.hoursId));
if (c.hoursId) {
const parsedChildId = parseInt(c.hoursId);
if (isNaN(parsedChildId)) {
throw new Error(`Invalid hoursId value for child: ${c.hoursId}`);
}
ids.push(parsedChildId);
}
});
}

return ids;
}

public async fetchHours() {
if (this.hoursId) {
// Fetch hours logic here
} else throw new Error(`hoursId is undefined`);
if (!this.hoursId) {
throw new Error(`hoursId is undefined`);
}

// If you fetch from an API:
// try {
// const response = await fetch(YOUR_API_ENDPOINT);
// const data = await response.json();
// // Handle the data here
// } catch (error) {
// throw new Error("Failed to fetch hours: " + error.message);
// }
}

constructor(init?: Partial<Library>) {
super(init);
}

public async getChildren() {
// Get children logic here
// Error handling should be similar to fetchHours
}

public async getParent() {
// Get parent logic here
// Error handling should be similar to fetchHours
}
}

export function parse(lib: {
relationships: any;
id: any;
interface ApiResponseShape {
relationships: {
field_parent?: {
data?: {
id?: string;
};
};
};
id: string;
attributes: {
title: any;
body: { processed: any };
field_short_title: any;
field_type_basic: any;
field_contact_form: any;
field_donor_description: any;
field_donor_title: any;
field_email_address: any;
field_hours_information: any;
field_libcal_id: any;
field_library_feed: any;
field_library_site_link: { uri: any };
field_location_key: any;
field_fm_location: { lat: any; lng: any };
field_mygroup_id: any;
field_phone_number: any;
field_social_media: { uri: any; title: any }[];
field_slug: any;
field_zip_code: any;
field_google_my_business: any;
field_parent: { data: { id: string | undefined } };
field_closure_override: any;
title: string;
body?: { processed: string };
field_short_title?: string;
field_type_basic?: string;
field_contact_form?: string;
field_donor_description?: string;
field_donor_title?: string;
field_email_address?: string;
field_hours_information?: { processed: string };
field_libcal_id?: string;
field_library_feed?: string;
field_library_site_link?: { uri: string };
field_location_key?: string;
field_fm_location?: { lat: string; lng: string };
field_mygroup_id?: string;
field_phone_number?: string;
field_social_media?: { uri: string; title: string }[];
field_slug?: string;
field_zip_code?: string;
field_google_my_business?: boolean;
field_closure_override?: number;
field_priority_placement?: number;
};
}) {
}

export function parse(lib: ApiResponseShape): Library {
if (!lib || !lib.id || !lib.attributes.title) {
throw new Error("Invalid library data provided.");
}

return new Library({
id: lib.id,
uuid: lib.id,
Expand All @@ -105,24 +147,23 @@ export function parse(lib: {
hoursId: lib.attributes.field_libcal_id,
libraryFeed: lib.attributes.field_library_feed,
link: lib.attributes.field_library_site_link?.uri,
siteLink: lib.attributes.field_library_site_link?.uri.replace("internal:","https://www.library.virginia.edu"),
siteLink: {
title: lib.attributes.field_library_site_link?.uri ?? "",
uri: lib.attributes.field_library_site_link?.uri.replace("internal:", SITE_LINK_BASE) ?? ""
},
fmKey: lib.attributes.field_location_key,
location: lib.attributes.field_fm_location ? {
lat: lib.attributes.field_fm_location.lat,
lng: lib.attributes.field_fm_location.lng
} : undefined,
mygroupId: lib.attributes.field_mygroup_id,
phoneNumber: lib.attributes.field_phone_number,
socialMedia: lib.attributes.field_social_media ?
lib.attributes.field_social_media.map((sm: { uri: any; title: any }) => ({ uri: sm.uri, title: sm.title })) :
undefined,
socialMedia: lib.attributes.field_social_media?.map(sm => ({ uri: sm.uri, title: sm.title })),
slug: lib.attributes.field_slug,
zipCode: lib.attributes.field_zip_code,
googleMyBusiness: lib.attributes.field_google_my_business,
parent: lib.relationships.field_parent && lib.relationships.field_parent.data && lib.relationships.field_parent.data.id ?
lib.relationships.field_parent.data.id :
undefined,
closureOverride: lib.attributes.field_closure_override
parent: lib.relationships.field_parent?.data?.id,
closureOverride: lib.attributes.field_closure_override,
priorityPlacement: lib.attributes.field_priority_placement
});
}

75 changes: 55 additions & 20 deletions packages/site-hours/src/SiteHoursSection.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,60 @@

/* eslint-disable no-nested-ternary */
import { html, css, LitElement } from 'lit';
import { property } from 'lit/decorators.js';
import { SiteStyle } from '@uvalib/site-style';
import { LibrariesData, Library } from '@uvalib/data-wrap';
import { Hours } from '@uvalib/data-wrap/dist/src/Hours';
import {unsafeHTML} from 'lit/directives/unsafe-html.js';
import { printTimesForLibrary, sortLibraries } from './utils';
import { printTimesForLibrary } from './utils';

// Main class for SiteHoursSection
export class SiteHoursSection extends SiteStyle {
/**
* Function to sort libraries based on priorityPlacement and title.
* Libraries with defined priorityPlacement come first, sorted by the value.
* Libraries without priorityPlacement come later and are sorted by their title.
*/
function sortLibraries(libs: Library[]) {
return libs.sort((a, b) => {
if (a.priorityPlacement && b.priorityPlacement) {
// Check if both titles are defined before comparing
if (a.title && b.title) {
return a.priorityPlacement - b.priorityPlacement || a.title.localeCompare(b.title);
}
return a.priorityPlacement - b.priorityPlacement;
}
if (a.priorityPlacement && !b.priorityPlacement) {
return -1;
}
if (!a.priorityPlacement && b.priorityPlacement) {
return 1;
}
// Check if both titles are defined before comparing
if (a.title && b.title) {
return a.title.localeCompare(b.title);
}
return 0; // If titles are not defined, consider them equal
});
}

// Formatted date property
@property({type:String}) formattedDate = new Intl.DateTimeFormat('en-US', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric', timeZone: 'America/New_York' }).format( new Date() );

// Place type property
/**
* SiteHoursSection class represents a component that displays the hours of various locations.
* It extends the SiteStyle class to inherit styling functionalities.
*/
export class SiteHoursSection extends SiteStyle {

// The current date formatted for display
@property({type:String}) formattedDate = new Intl.DateTimeFormat('en-US', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric', timeZone: 'America/New_York' }).format( new Date() );

// Type of place (like 'Library', 'Cafe', etc.) to filter libraries
@property({type:String, attribute:"place-type"}) placeType = null;

// limited property flags
// Flag to filter libraries based on priorityPlacement
@property({type:Boolean}) limited = false;

// Libraries array property
// List of libraries fetched and processed
@property({type:Array}) libraries: Library[] = [];

// Class constructor, initializes libraries data
// Constructor initializes data fetching
constructor() {
super();
const libraries = new LibrariesData();
Expand All @@ -32,17 +63,21 @@ export class SiteHoursSection extends SiteStyle {
});
}

// Initialize libraries data and fetch hours
/**
* Fetch libraries data, filter based on specified criteria, and then sort.
*/
async initializeLibrariesData(libraries: LibrariesData) {
try {
await libraries.fetchData();
await libraries.fetchHours();
// Filter and sort libraries

console.log(libraries.items);
this.libraries = sortLibraries(libraries.items
.filter(lib => this.placeType ? lib.placeType === this.placeType : true)
.filter(lib => this.limited ? lib.placeType === 'Library' && lib.hours : true));
.filter(lib => this.limited ? lib.priorityPlacement && lib.priorityPlacement > 0 : true));
console.log(this.libraries);

// Dispatch custom events
// Dispatch custom events to notify other components or listeners
this.dispatchEvent(new CustomEvent('got-library-hours', {
detail: { message: 'fetched hours for libraries' },
bubbles: true,
Expand All @@ -58,19 +93,19 @@ export class SiteHoursSection extends SiteStyle {
}
}

// Print raw dates
// Helper function to format raw date-times for a library
private _printRawDates(lib:Library){
return printTimesForLibrary(lib);
}

// Render method for the component
// Component render function to define its HTML structure
render() {
return html`
<div class="home-hours-block">
<div id="homehoursdate" class="home-hour-date">${this.formattedDate}</div>
<h3 class="hour-head">Today's hours</h3>
<dl class="dl--inline hours-locations">
${this.libraries.map(lib=>html`
${this.libraries.map(lib => html`
<dt class="location">${lib.shortTitle? lib.shortTitle:lib.title}</dt>
<dd class="hours">${lib.hours?
lib.hours.rawDates?
Expand All @@ -91,4 +126,4 @@ export class SiteHoursSection extends SiteStyle {
</div>
`;
}
}
}

0 comments on commit 5642ec5

Please sign in to comment.